| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
- Python
- ASR
- LangGraph
- dementional reduction
- 머신러닝
- 랭그래프
- 트랜스포머
- 데이터엔지니어
- RNN
- 알고리즘
- CLIP
- 소프트웨어 개발
- 에이전트
- 기초
- python 기초
- python기초
- RDBMS
- SQL
- TTS
- Transformer
- 데이터 시각화
- 객체지향
- 생성형 인공지능
- 딥러닝
- UMAP
- 정보처리기사
- 자연어처리
- 캐글
- CNN
- 힙정렬
- Today
- Total
수달이네 기술 블로그
12. 주택 임대료 예측 2 본문
지난번에 이어 주택 임대료 예측을 할 것
원핫 인코딩
import pandas as pd
df = pd.get_dummies(df, columns=['Area Type', 'City', 'Furnishing Status', 'Tenant Preferred', 'Point of Contact'], drop_first=True)
df.head()
get_dummies 함수를 이용하여 원핫 인코딩 해준다.
01234
| BHK | Rent | Size | Bathroom | Area Type_Carpet Area | Area Type_Super Area | City_Chennai | City_Delhi | City_Hyderabad | City_Kolkata | City_Mumbai | Furnishing Status_Semi-Furnished | Furnishing Status_Unfurnished | Tenant Preferred_Bachelors/Family | Tenant Preferred_Family | Point of Contact_Contact Builder | Point of Contact_Contact Owner |
| 2 | 10000 | 1100 | 2 | False | True | False | False | False | True | False | False | True | True | False | False | True |
| 2 | 20000 | 800 | 1 | False | True | False | False | False | True | False | True | False | True | False | False | True |
| 2 | 17000 | 1000 | 1 | False | True | False | False | False | True | False | True | False | True | False | False | True |
| 2 | 10000 | 800 | 1 | False | True | False | False | False | True | False | False | True | True | False | False | True |
| 2 | 7500 | 850 | 1 | True | False | False | False | False | True | False | False | True | False | False | False | True |
위와 같이 컬럼이 늘어나는 것을 볼 수 있다.
변수 분리
독립변수, 종속변수 분리
X = df.drop('Rent', axis=1)
- 독립변수를 만들기 위해 target값을 제외한 나머지를 X로
y = df['Rent']
- 종속변수를 만들기 위해 target값을 y로 둔다.
독립변수, 종속변수 에서 train, test값 분리
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=2026
)
train값과 test값을 나누어 준다.
학습
Linear Regression
사이킷 런의 선형 회귀 학습 방법으로, 최소 제곱법을 기반으로 학습하여, 입력 데이터와 실제 목표값 사이의 잔차(Residual)의 제갑합을 최소화 하는 식으로 최적의 가중치(Weight)와 절편(Bias)을 구함.
- 원칙은 위로 계산하지만 사이킷 런에서는 SVD(특이값 분해)를 사용해 계산한다.
최소 제곱법(Least Squares Method)
주어진 데이터 포인트들과 예측 모델 사이의 오차의 제곱합을 최소화하여 최적 예측 모델을 찾아내는 통계적 방법

실제 관측값과 예측값(예측선) 사이의 차이를 구하여, 해당 값을 제곱하고, 변해야 할 방향으로 예측값을 움직인다.
- 선을 그려서 예측값을 찾아가기 때문에 Linear Regression이라 한다.
from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(X_train, y_train)
y_pred = lr.predict(X_test)
- 이전에 했던 방식과 같이 학습 가능하다.
분류 예측의 경우 Accuracy를 이용하여 맞은 것의 비율을 알 수 있지만, 회귀는 맞았다 틀렸다로 구분할 수 없다.
- 따라서, MSE같은 방식으로 평가한다.
평가지표
MSE: mean squared error
- 예측선과 실제 관측값 사이의 차이를 제곱한 평균값
RMSE: root mean squared error
- 예측선과 실제 관측값 사이의 차이를 제곱한 후 루트를 씌워준 평균값
from sklearn.metrics import root_mean_squared_error, mean_squared_error
print(mean_squared_error(y_test, y_pred))
print(root_mean_squared_error(y_test, y_pred))
# 1672630733.35432
# 40897.808417497385
- 위는 오차값을 뽑아낸 것이다.
- 즉, 값이 작을수록 좋다.
- 해당 오차를 줄일 수 있는 방식은 없을까?
오차 감소
이상치 제거
sns.boxplot(df['Rent'])

위는 Rent 컬럼에서의 이상치를 확인한 것인데,
- 3.5부분에 유난히 튀어있는 이상치를 제거해야겠다.
df_sort = df['Rent'].sort_values()
df_sort
# 4076 1200
# 285 1500
# 471 1800
# 2475 2000
# 506 2200
# ...
# 1459 700000
# 1329 850000
# 827 1000000
# 1001 1200000
# 1837 3500000
해당 값이 1837 이라는 것을 확인했고,해당 컬럼을 삭제해준다.
X_train.drop(1837, axis=0, inplace=True)
y_train.drop(1837, axis=0, inplace=True)
위와 같은 방식으로 삭제해준다.
lr = LinearRegression()
lr.fit(X_train, y_train)
new_y_pred = lr.predict(X_test)
root_mean_squared_error(y_test, new_y_pred)
# 40935.356510776386
오히려 값이 나빠졌다는 것을 알 수 있다.
그러면 굳이 해당 전처리를 해줄 필요가 없음을 알 수 있다.
왜?
만약 해당 값이 선형으로 되어있다면,

이상치를 제거하는 것으로 효과를 볼 수 있었겠으나,
해당값이 만약

위와 같이 지수함수의 형태로 나타난다면,
오히려 이상치를 제거한 것이 오류를 일으켰을 가능성이 있다.
그러면 우리는 데이터가 곡선형이거나, 비선형일 가능성을 생각해둘 수 있다.
로그 변환으로 RMSE 개선
데이터를 로그변환하여 값의 범위를 축소하고, 분포를 정규분포에 가깝게 만들 수 있다.
- 지수함수를 로그변환하여 선형으로 만들어줌
데이터 변환
원본 데이터: 실제 데이터 값(Rent: 1000, 10000등)
로그 변환 데이터: 데이터의 비율(log(1000), log(10000)으로 변환)
데이터의 값은 변하나 관계는 변환하지 않는다.
최종 예측시에는 원래 스케일로 만들어준다.
import numpy as np
y_train = np.log1p(y_train) #로그 변환
y_test = np.log1p(y_test)
lr = LinearRegression()
lr.fit(X_train, y_train)
y_log_pred = lr.predict(X_test)
log_pred = np.expm1(y_log_pred) #원래대로 되돌림
y_test_ori = np.expm1(y_test) #원래대로 되돌림
root_mean_squared_error(y_test_ori, log_pred)
# 35053.775776517024
넘파이의 log1p메서드를 이용하여 로그변환시켜준다.
이후 해당 값으로 학습 시켜준 다음 다시 변환시켜주면
RMSE의 값이 많이 감소한 것을 확인할 수 있다.
- 40897 > 35053
앙상블 모델 적용
앙상블: 여러개의 머신러닝 모델을 조합하여 하나의 강력한 예측 모델을 만드는 방식
장점
- 각 개별 모델이 가진 장점을 결합, 약점을 보완 가능
기법
- 배깅(Bagging), 부스팅(Boosting), 스태킹(Stacking)
- 랜덤 포레스트, XGBoost등은 배깅과 부스팅을 대표하는 알고리즘이다.
- 배깅: 같은 모델을 여러개 쓰는 것.
- 부스팅: 학습을 시킨 후 나온 결과를 또 다시 모델에 넣어주는 방식을 사용 > 과적합 가능성 높음
랜덤포레스트
결정트리(Decision Tree)를 결합해 예측을 수행하는 앙상블 학습 방법.
- 각각의 트리가 무작위로 선택된 데이터 샘플과 특성을 사용해 학습된다. 분류 문제에선 다수결 투표, 회귀문제에선 평균을 통해 최종 예측값을 도출한다.
- 과적합 위험이 감소된 안정적 성능을 보장하고, 이상치에 강하다.
XGBoost
그래디언트 부스팅 알고리즘을 기반으로 한 머신러닝 앙상블 모델
- 결정 트리등의 약한 학습기를 순차적으로 학습시키고, 이전 트리의 오차를 보정해 예측 성능을 개선
- 정확도, 속도, 과적합 방지에서 성능이 좋음.
from sklearn.ensemble import RandomForestRegressor
from xgboost import XGBRegressor
models = {
'LinearRegression': LinearRegression(),
'RandomForest': RandomForestRegressor(),
'XGBoost': XGBRegressor()
}
results = {}
for model_name, model in models.items():
model.fit(X_train, y_train)
y_log_pred = model.predict(X_test)
log_pred = np.expm1(y_log_pred)
y_test_ori = np.expm1(y_test)
rmse = root_mean_squared_error(y_test_ori, log_pred)
results[model_name] = rmse
print(f"{model_name}: {rmse:.2f}")
best_model_name = min(results, key=results.get)
print(f"Best model: {best_model_name} with RMSE: {results[best_model_name]:.2f}")
# LinearRegression: 35053.78
# RandomForest: 33369.09
# XGBoost: 35549.04
# Best model: RandomForest with RMSE: 33369.09
- 위 세 모델을 한번에 넣어두고 반복문을 통해 세 모델을 따로따로 학습시킨 다음 최적의 모델을 확인할 수 있다.
- 위에선 랜덤포레스트가 베스트 모델임을 알 수 있다.
'AI공부 > 머신러닝' 카테고리의 다른 글
| 14. 서울 따릉이 대여 수요 예측 (0) | 2026.01.06 |
|---|---|
| 13. 자전거 대여 수요 예측 (0) | 2026.01.02 |
| 11. 주택 임대료 예측 (1) | 2025.12.29 |
| 10. Iris 데이터셋 예측(머신러닝 입문) (0) | 2025.12.28 |
| 8. 머신러닝 기초 (1) | 2025.12.10 |