2.6 모델 선택과 훈련

2.5 머신러닝 알고리즘을 위한 데이터 준비 | 목차 | 2.7 모델 세부 튜닝

 

드디어 마지막입니다! 문제를 정의한 후 데이터를 읽어 들이고 탐색했습니다. 그리고 훈련 세트와 테스트 세트로 나누고 머신러닝 알고리즘에 주입할 데이터를 자동으로 정제하고 준비하기 위해 변환 파이프라인을 작성했습니다. 이제 머신러닝 모델을 선택하고 훈련시킬 준비가 되었습니다.

 

2.6.1 훈련 세트에서 훈련하고 평가하기

이전 단계의 작업 덕분에 생각보다 훨씬 간단해졌습니다. 먼저 앞 장에서 했던 것처럼 선형 회귀 모델을 훈련시켜보겠습니다.

from sklearn.linear_model import LinearRegression

lin_reg = LinearRegression()
lin_reg.fit(housing_prepared, housing_labels)

이게 끝입니다! 완전히 작동하는 선형 회귀 모델을 만들었습니다. 훈련 세트에 있는 몇 개 샘플에 대해 적용해보겠습니다.

>>> some_data = housing.iloc[:5]
>>> some_labels = housing_labels.iloc[:5]
>>> some_data_prepared = full_pipeline.transform(some_data)
>>> print("예측: ", lin_reg.predict(some_data_prepared))
예측: [ 210644.6045 317768.8069 210956.4333 59218.9888 189747.5584]
>>> print("레이블: ", list(some_labels))
레이블: [286600.0, 340600.0, 196900.0, 46300.0, 254500.0]

아주 정확한 예측은 아니지만(예를 들어 첫 번째 예측은 40% 가까이 벗어났습니다) 작동은 합니다. 사이킷런의 mean_square_error 함수를 사용해 전체 훈련 세트에 대한 이 회귀 모델의 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)
>>> lin_rmse
68628.198198489219

좋습니다. 없는 것보다는 낫지만 확실히 좋은 점수는 아닙니다. 대부분 구역의 중간 주택 가격은 $120,000에서 $265,000 사이입니다. 그러므로 예측 오차가 $68,628인 것은 매우 만족스럽지 못합니다. 이는 모델이 훈련 데이터에 과소적합된 사례입니다. 이런 상황은 특성들이 좋은 예측을 만들만큼 충분한 정보를 제공하지 못했거나 모델이 충분히 강력하지 못하다는 사실을 말해줍니다. 앞 장에서 보았듯이 과소적합을 해결하는 주요 방법은 더 강력한 모델을 선택하거나 훈련 알고리즘에 더 좋은 특성을 주입하거나 모델의 규제를 감소시키는 것입니다. 이 모델은 규제를 사용하지 않았으므로 마지막 옵션은 제외됩니다. 특성을 더 많이 추가할 수 있지만(예를 들면 로그 스케일된 인구), 먼저 더 복잡한 모델을 시도해서 어떻게 되는지 보겠습니다.

DecisionTreeRegressor를 훈련시켜보겠습니다. 이 모델은 강력하고 데이터에서 복잡한 비선형 관계를 찾을 수 있습니다(결정 트리에 대해서는 6장에서 자세히 설명합니다). 다음 코드는 이전과 비슷합니다.

from sklearn.tree import DecisionTreeRegressor

tree_reg = DecisionTreeRegressor()
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)
>>> tree_rmse
0.0

잠깐만요, 뭐죠!? 오차가 전혀 없나요? 이 모델이 진짜 완벽할 수 있나요? 물론 이는 모델이 데이터에 너무 심하게 과대적합된 것으로 보입니다. 어떻게 확신할 수 있죠? 앞서 이야기했듯이 여러분은 확신이 드는 모델이 론칭할 준비가 되기 전까지 테스트 세트는 사용하지 않으려 하므로 훈련 세트의 일부분으로 훈련을 하고 다른 일부분은 모델 검증에 사용해야 합니다.

 

2.6.2 교차 검증을 사용한 평가

결정 트리 모델을 평가하는 방법을 생각해보겠습니다. 우선 train_test_split 함수를 사용해 훈련 세트를 더 작은 훈련 세트와 검증 세트로 나누고, 더 작은 훈련 세트에서 모델을 훈련시키고 검증 세트로 모델을 평가하는 방법이 있습니다. 조금 수고스럽지만 너무 어렵지 않으며 매우 잘 작동합니다.

훌륭한 대안으로 사이킷런의 교차 검증 기능을 사용하는 방법도 있습니다. 다음 코드는 K-겹 교차 검증K-fold cross-validation을 수행합니다. 훈련 세트를 폴드fold라 불리는 10개의 서브셋으로 무작위로 분할합니다. 그런 다음 결정 트리 모델을 10번 훈련하고 평가하는데, 매번 다른 폴드를 선택해 평가에 사용하고 나머지 9개 폴드는 훈련에 사용합니다. 10개의 평가 점수가 담긴 배열이 결과가 됩니다.

from sklearn.model_selection import cross_val_score
scores = cross_val_score(tree_reg, housing_prepared, housing_labels,
                         scoring="neg_mean_squared_error", cv=10)
tree_rmse_scores = np.sqrt(-scores)
CAUTION_ 사이킷런의 교차 검증 기능은 scoring 매개변수에 (낮을수록 좋은) 비용 함수가 아니라 (클수록 좋은) 효용 함수를 기대합니다. 그래서 평균 제곱 오차(MSE)의 반댓값(즉, 음숫값)을 계산하는 neg_mean_squared_error 함수를 사용합니다. 이런 이유로 앞선 코드에서 제곱근을 계산하기 전에 -scores로 부호를 바꿨습니다.50

결과를 살펴보겠습니다.

>>> def display_scores(scores):
...     print("Scores:", scores)
...     print("Mean:", scores.mean())
...     print("Standard deviation:", scores.std())
...
>>> display_scores(tree_rmse_scores)
Scores: [ 70232.0136482 66828.46839892 72444.08721003 70761.50186201
          71125.52697653 75581.29319857 70169.59286164 70055.37863456
          75370.49116773 71222.39081244]
Mean: 71379.0744771
Standard deviation: 2458.31882043

결정 트리 결과가 이전만큼 좋아 보이지 않습니다. 실제로 선형 회귀 모델보다 나쁩니다! 교차 검증으로 모델의 성능을 추정하는 것뿐만 아니라 이 추정이 얼마나 정확한지(즉, 표준편차) 측정할 수 있습니다. 결정 트리 점수가 대략 평균 71,379에서 ±2,458 사이입니다. 검증 세트를 하나만 사용했다면 이런 정보를 얻지 못했을 것입니다. 하지만 모델을 여러 번 훈련시켜야 해서 비용이 비싸므로 교차 검증을 언제나 쓸 수 있는 것은 아닙니다.

비교를 위해 선형 회귀 모델의 점수를 계산해보겠습니다.

>>> lin_scores = cross_val_score(lin_reg, housing_prepared, housing_labels,
...                              scoring="neg_mean_squared_error", cv=10)
...
>>> lin_rmse_scores = np.sqrt(-lin_scores)
>>> display_scores(lin_rmse_scores)
Scores: [ 66760.97371572 66962.61914244 70349.94853401 74757.02629506
          68031.13388938 71193.84183426 64968.13706527 68261.95557897
          71527.64217874 67665.10082067]
Mean: 69047.8379055
Standard deviation: 2735.51074287

확실히 결정 트리 모델이 과대적합되어 선형 회귀 모델보다 성능이 나쁩니다. 마지막으로 RandomForestRegressor 모델을 하나 더 시도해보겠습니다. 7장에서 보게 되겠지만 랜덤 포레스트는 특성을 무작위로 선택해서 많은 결정 트리를 만들고 그 예측을 평균 내는 방식으로 작동합니다. 여러 다른 모델을 모아서 하나의 모델을 만드는 것을 앙상블 학습이라고 하며 머신러닝 알고리즘의 성능을 극대화하는 방법 중 하나입니다. 다른 모델들과 기본적으로 비슷하므로 코드 설명은 대부분 건너뛰도록 하겠습니다.

>>> from sklearn.ensemble import RandomForestRegressor
>>> forest_reg = RandomForestRegressor()
>>> forest_reg.fit(housing_prepared, housing_labels)
>>> [...]
>>> forest_rmse
21941.911027380233
>>> display_scores(forest_rmse_scores)
Scores: [ 51650.94405471 48920.80645498 52979.16096752 54412.74042021
          50861.29381163 56488.55699727 51866.90120786 49752.24599537
          55399.50713191 53309.74548294]
Mean: 52564.1902524
Standard deviation: 2301.87380392

오, 훨씬 좋네요. 랜덤 포레스트는 매우 훌륭해 보입니다. 하지만 훈련 세트에 대한 점수가 검증 세트에 대한 점수보다 훨씬 낮으므로 이 모델도 여전히 훈련 세트에 과대적합되어 있습니다. 과대적합을 해결하는 방법은 모델을 간단히 하거나, 제한을 하거나(즉, 규제), 더 많은 훈련 데이터를 모으는 것입니다. 그러나 랜덤 포레스트를 더 깊이 들어가기 전에, 여러 종류의 머신러닝 알고리즘으로 하이퍼파라미터 조정에 너무 많은 시간을 들이지 않으면서 다양한 모델(다양한 커널의 서포트 벡터 머신, 신경망 등)을 시도해봐야 합니다. 가능성 있는 2~5개 정도의 모델을 선정하는 것이 목적입니다.

TIP 실험한 모델을 모두 저장해두면 필요할 때 쉽게 모델을 복원할 수 있습니다. 교차 검증 점수와 실제 예측값은 물론 하이퍼파라미터와 훈련된 모델 파라미터 모두 저장해야 합니다. 이렇게 하면 여러 모델의 점수와 모델이 만든 오차를 쉽게 비교할 수 있습니다. 파이썬의 pickle 패키지나 (넘파이 배열을 저장하는 데 아주 효율적인) sklearn.externals.joblib을 사용하여 사이킷런 모델을 간단하게 저장할 수 있습니다.

from sklearn.externals import joblib

joblib.dump(my_model, "my_model.pkl")
# 그리고 나중에...
my_model_loaded = joblib.load("my_model.pkl")

 


 

50 옮긴이_ 평균 제곱 오차가 작을수록 좋은 비용 함수이므로 부호가 반대가 되어야 scoring 매개변수 정의에 맞습니다. 회귀 모델에서 scoring 매개변수를 지정하지 않으면 기본적으로 0~1 사이의 값을 가지는 r2_score가 사용됩니다. scoring 매개변수에 사용할수 있는 전체 목록은 다음 주소를 참고하세요. https://goo.gl/C7kSgU

 

2.5 머신러닝 알고리즘을 위한 데이터 준비 | 목차 | 2.7 모델 세부 튜닝

 

이 글은 한빛미디어에서 출간한  “핸즈온 머신러닝“의 1장과 2장입니다. 이 책의 저작권은 한빛미디어(주)에 있으므로 무단 복제 및 무단 전제를 금합니다.

2.6 모델 선택과 훈련”에 대한 3개의 생각

  1. 김태완

    휴일에 죄송하지만 궁금한 것 한가지 질문하겠습니다.
    제가 손글씨 인식 모델을 사이킷런의 SVM으로 학습시키고 검증을 하게 했습니다. 정답률은 0.95정도이더군요. 그런데 여기서 멈추지 않고 어떤 데이터(손글씨 이미지)를 하나 넣어 주면 모델이 학습한 대로 모델이 입력값에 대한 정답을 예측하게 할 수는 없나요?

    좋아요

    응답

답글 남기기

아래 항목을 채우거나 오른쪽 아이콘 중 하나를 클릭하여 로그 인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 /  변경 )

%s에 연결하는 중

This site uses Akismet to reduce spam. Learn how your comment data is processed.