3 minute read

지금까지 한 작업

  • 문제 정의
  • 데이터 읽고 탐색
  • 훈련 세트와 테스트 세트 나누기
  • 데이터를 자동으로 정제하고 준비하는 변환 파이프라인 작성
# 데이터 불러오기
import pandas as pd
import numpy as np
housing_prepared = pd.read_csv("housing_prepared.csv", index_col=0).reset_index(drop=True)
housing_labels = pd.read_csv("housing_labels.csv", index_col=0).reset_index(drop=True)
housing = pd.read_csv("housing.csv", index_col=0).reset_index(drop=True)
print(housing_labels.iloc[:5])
median_house_value
0 72100.0
1 279600.0
2 82700.0
3 112500.0
4 238300.0

class로 만들어둔 파이프라인 객체 만들기

from functions.full_pipeline import FullPipeline 
full_pipeline = FullPipeline()

housing_prepared = full_pipeline.fit_transform(housing)

선형 회귀 모델 시도해보기

# 선형 회귀 모델 훈련
from sklearn.linear_model import LinearRegression

lin_reg = LinearRegression()
lin_reg.fit(housing_prepared, housing_labels)
LinearRegression()
# 훈련 세트에 있는 몇 개 샘플에 대해 적용
some_data = housing.iloc[:5]
some_labels = housing_labels.iloc[:5]
# some_labels to list
some_labels = some_labels.values.tolist()

some_data_prepared = full_pipeline.transform(some_data)

print("예측:", lin_reg.predict(some_data_prepared))
print("레이블:", some_labels)
예측: [[ 86208.]
[304704.]
[153536.]
[185728.]
[244416.]]
레이블: [[72100.0], [279600.0], [82700.0], [112500.0], [238300.0]]

선형 회귀 모델 RMSE 측정

from sklearn.metrics import mean_squared_error
housing_predictions = lin_reg.predict(housing_prepared)
lin_mse = mean_squared_error(housing_labels, housing_predictions)
lin_rmse = np.sqrt(lin_mse)
print("선형 회귀 모델의 RMSE:", lin_rmse)
선형 회귀 모델의 RMSE: 68633.40810776998

해석

  • 대부분 구역의 중간 주택 가격은 120,000 ~ 265,000 사이
  • 68000가량의 오차는 예측이 전혀 수행되지 못하고 있다는 뜻
  • 모델이 훈련 데이터에 과소적합된 것
  • 특성들이 좋은 예측을 만들 만큼 충분한 정보를 제공하지 못했거나
  • 모델이 충분히 강력하지 않았다는 것

  • 과소적합을 해결하려면
    1. 더 강력한 모델을 선택하거나
    2. 훈련 알고리즘에 더 좋은 특성을 주입하거나
    3. 규제를 감소시키는 것

여기서는 규제를 도입한 적이 없으므로 일단 더 복잡한 모델을 선택하는 것으로 시도해보자

Decision Tree Regressor

  • 데이터에서 복잡한 비선형 관계를 찾을 수 있는 모델
from sklearn.tree import DecisionTreeRegressor

tree_reg = DecisionTreeRegressor(random_state=42)
tree_reg.fit(housing_prepared, housing_labels)

housing_predictions = tree_reg.predict(housing_prepared)
tree_mse = mean_squared_error(housing_labels, housing_predictions)
tree_rmse = np.sqrt(tree_mse)
print("결정 트리 모델의 RMSE:", tree_rmse)
결정 트리 모델의 RMSE: 0.0

결과 해석

  • 오차가 전혀 없음
  • 모델이 데이터에 너무 심하게 과대적합된 것으로 보임
  • 교차 검증을 시도해봐야 함

K-fold 교차 검증

  • 예를 들어 10겹 교차 검증은 아래와 같음
  • 훈련 세트를 10개의 서브셋으로 무작위 분할
  • 결정 트리 모델을 10번 훈련하고 평가함
  • 매 번 하나의 다른 폴드를 선택해 평가에 사용
  • 나머지 9개 폴드는 훈련에 사용
  • 10개의 평가 점수가 담긴 배열이 결과로 나옴
from sklearn.model_selection import cross_val_score
scores = cross_val_score(tree_reg, housing_prepared, housing_labels, cv=10)

rmse_scores = cross_val_score(tree_reg, housing_prepared, housing_labels, 
                              scoring="neg_mean_squared_error", cv=10)

def display_rmse_scores(rmsescores):
  rmse_adj = np.sqrt(-rmsescores)
  print("rmse_scores:", rmse_adj)
  print("rmse 평균:", rmse_adj.mean())
  print("rmse 표준편차:", rmse_adj.std())



print('r2_scores: ', scores)
display_rmse_scores(rmse_scores)
r2_scores: [0.59448979 0.63522832 0.61936099 0.61651153 0.62440093 0.55585695
0.64931478 0.59497473 0.6425953 0.62572699]
rmse_scores: [72831.45749112 69973.18438322 69528.56551415 72517.78229792
69145.50006909 79094.74123727 68960.045444 73344.50225684
69826.02473916 71077.09753998]
rmse 평균: 71629.89009727491
rmse 표준편차: 2914.035468468928

해석

  • 기본적으로 scoring에 아무 매개변수가 없다면 r2_score를 계산한다
  • rmse를 계산하면 값이 음수로 나오기 때문에 양수로 바꾸고 표준편차를 구했다.
  • rmse score와 평균, 표준편차를 print하는 것은 뒤에서 더 사용할 예정이므로 함수로 구현했다
  • 결과는 선형회귀보다도 나빴다

RandomForest

  • 특성을 무작위로 선택해서 많은 결정 트리를 만들고 그 예측을 평균 냄
  • 여러 다른 모델을 모아서 하나의 모델을 만드는 것을 앙상블 학습이라고 함
  • 머신러닝 알고리즘의 성능을 극대화할 수 있음
print(housing_labels)
[ 72100. 279600. 82700. ... 140400. 258100. 62700.]
from sklearn.ensemble import RandomForestRegressor
forest_reg = RandomForestRegressor(n_estimators=100, random_state=42)

forest_reg.fit(housing_prepared, housing_labels)


forest_scores = cross_val_score(forest_reg, housing_prepared, housing_labels, cv=10)
forest_rmse_scores = cross_val_score(forest_reg, housing_prepared, housing_labels,
                                      scoring="neg_mean_squared_error", cv=10)

print('r2_scores: ', forest_scores)
display_rmse_scores(forest_rmse_scores)
r2_scores: [0.79677205 0.82303573 0.82450522 0.80376202 0.82217207 0.80903775
0.79483317 0.81127976 0.82639863 0.78352114]
rmse_scores: [51559.63379638 48737.57100062 47210.51269766 51875.21247297
47577.50470123 51863.27467888 52746.34645573 50065.1762751
48664.66818196 54055.90894609]
rmse 평균: 50435.58092066179
rmse 표준편차: 2203.3381412764606

모델 저장

  • 실험한 모델을 모두 저장해두면 필요할 때 쉽게 복원 가능
  • 하나의 알고리즘을 깊게 파기 전에 여러 종류의 알고리즘으로, 하이퍼파라미터 튜닝에 너무 큰 시간을 들이지 않으면서 다양한 모델을 시도해봐야 함
  • 그리고 가능성 있는 2~5개의 모델을 선정하고, 그것들을 깊게 파는 것
import joblib
joblib.dump(forest_reg, "forest_reg.pkl")
joblib.dump(lin_reg, "lin_reg.pkl")

# 모델 불러오기
# forest_reg_loaded = joblib.load("forest_reg.pkl")
# lin_reg_loaded = joblib.load("lin_reg.pkl")
['lin_reg.pkl']

Leave a comment