반응형

머신러닝 프로젝트 실행(6~7단계)


머신러닝 프로젝트 실행 순서는 

1. 문제를 정의하고 전체 그림 바라보기

2. 데이터 얻기

3. 인사이트를 찾기 위해 데이터 탐색하기

4. 기본 데이터 패턴을 머신러닝 알고리즘에 더 잘 노출할 수 있도록 데이터 준비하기

5. 다양한 모델을 탐색하고 그 중 가장 좋은 모델을 찾기

6. 모델을 알맞게 튜닝하고 멋진 솔루션으로 통합하기

7. 시스템 런칭, 모니터링과 유지하기

입니다.


지금까지, 1~5단계까지 살펴보았습니다. 이제 2단계만 살펴보면 마무리 될 것 같습니다. 


먼저, 

6. 모델을 알맞게 튜닝하고 멋진 솔루션으로 통합하기


이제 유망한 모델들을 가졌다고 가정해 봅시다. 

그럼, 이 모델들을 튜닝하는 것이 필요합니다. 

실행할 수 있는 몇가지 방법을 살펴보도록 하겠습니다.


그리드 서치(Grid Search)


모델 튜닝을 수행하는 한 가지 방법은 하이퍼파라미터 값들의 좋은 조합을 찾아낼 때까지, 수동으로 하이퍼파라미터(hyperparameters)를 사용하는 것입니다. 

이것은 매우 지루한 작업이 될 것이고, 많은 조합을 탐색할만한 시간을 갖고 있지 않을 수도 있습니다.

그 대신에, 사이킷런(Scikit-Learn)의 GridSearchCV로 탐색을 하도록 할 수 있습니다. 

해야할 일 전부는 어떤 하이퍼파라미터를 실험하고 싶은지, 어떤 값들을 시험해 보아야 하는지를 알려주는 것입니다. 

그러면, 교차검증(cross-validation)을 사용해, 하이퍼파라미터 값들의 모든 가능한 조합들을 평가할 것입니다. 

예를 들어, 다음의 코드는 RnadomForestRegreesor를 위해 하이퍼파라미터 값들에 대한 최상의 조합을 검색합니다. 

>>> from sklearn.model_selection import GridSearchCV

>>> param_grid = [

{'n_estimators': [3, 10, 30], 'max_features': [2, 4, 6, 8]},

{'bootstrap': [False], 'n_estimators': [3, 10], 'max_features': [2, 3, 4]},

]

>>> forest_reg = RandomForestRegressor()

>>> grid_search = GridSearchCV(forest_reg, param_grid, cv=5,

scoring='neg_mean_squared_error')

>>> grid_search.fit(housing_prepared, housing_labels)


팁) 하이퍼파라미터가 어떤 값을 가져야 할지 알 수 없을 때, 간단한 접근법은 연속적으로 10의 파워를 시도해 보는 것입니다. (또는 더 세분화된 탐색을 원한다면, 더 작은 숫자로 시도: n_estimators 하이퍼파라미터를 가진 위 예에서 보듯이)


위 param_grid는 사이킷런에게 처음에 n_estimators의 모든 3×4 = 12개의 조합과 첫번째 dict에서 특정한 max_features 하이퍼파라미터 값들을 평가하도록 알려줍니다. 

그 다음에 두번째 dict인 모든 2×3 = 6개의 하이퍼파라미터 값들의 조합을 시도합니다. 

하지만, 이번에는 bootstrap 하이퍼파라미터는 True(이 하이퍼파라미터의 기본값이 True임) 대신에 False를 설정합니다.

전체적으로, 그리드 서치(grid search)는 RandomForestRegressor 하이퍼파라미터 값들의 12+6 =18개 조합들을 탐색할 것입니다. 

그리고 각 모델을 5번씩(왜냐하면 five-fold 교차검증을 사용하기 때문) 훈련시킬 것입니다. 

달리 말하자면 전체적으로, 18×5 = 90번의 훈련 라운드가 될 것입니다. 

아주 많은 시간이 걸리겠지만, 아래와 같이 최상의 파라미터 조합을 얻게 될 것입니다.

>>> grid_search.best_params_

{'max_features': 6, 'n_estimators': 30}


팁) n_estimators의 최대값이 30으로 평가되었습니다. 점수가 지속적으로 향상될 수도 있기 때문에, 더 높은 값도 평가해 보아야 할 것입니다.


직접 최상의 평가자(estimator)를 얻을 수도 있습니다.

>>> grid_search.best_estimator_

RandomForestRegressor(bootstrap=True, criterion='mse', max_depth=None,

max_feature=6, max_leaf_nodes=None, min_samples_leaf=1,

min_samples_split=2, min_weight_fraction_leaf=0.0,

n_estimators=30, n_jobs=1, oob_score=False, random_state=None,

verbose=0, warm_start=False)


론 평가 점수들도 이용할 수 있습니다.

>>> cvres = grid_search.cv_results_

... for mean_score, params in zip(cvres["mean_test_score"], cvres["params"]):

...        print(np.sqrt(-mean_score), params)

...

64912.0351358 {'max_features': 2, 'n_estimators': 3}

55535.2786524 {'max_features': 2, 'n_estimators': 10}

52940.2696165 {'max_features': 2, 'n_estimators': 30}

60384.0908354 {'max_features': 4, 'n_estimators': 3}

52709.9199934 {'max_features': 4, 'n_estimators': 10}

50503.5985321 {'max_features': 4, 'n_estimators': 30}

59058.1153485 {'max_features': 6, 'n_estimators': 3}

52172.0292957 {'max_features': 6, 'n_estimators': 10}

49958.9555932 {'max_features': 6, 'n_estimators': 30}

59122.260006 {'max_features': 8, 'n_estimators': 3}

52441.5896087 {'max_features': 8, 'n_estimators': 10}

50041.4899416 {'max_features': 8, 'n_estimators': 30}

62371.1221202 {'bootstrap': False, 'max_features': 2, 'n_estimators': 3}

54572.2557534 {'bootstrap': False, 'max_features': 2, 'n_estimators': 10}

59634.0533132 {'bootstrap': False, 'max_features': 3, 'n_estimators': 3}

52456.0883904 {'bootstrap': False, 'max_features': 3, 'n_estimators': 10}

58825.665239 {'bootstrap': False, 'max_features': 4, 'n_estimators': 3}

52012.9945396 {'bootstrap': False, 'max_features': 4, 'n_estimators': 10}


위 예에서, max_features 하이퍼파라미터를 6으로, n_estimators 하이퍼파라미터를 30으로 설정함으로써 최상의 해결책을 확보할 수 있습니다. 

이 조합의 RMSE 점수는 49,959입니다. 

기본 하이퍼파라미터 값들(점수가 52,634)을 사용한 경우보다 더 좋은 점수를 얻었기 때문에 약간 더 좋아졌습니다. 

성공적으로 최상의 모델로 잘 튜닝했습니다!


팁) 하이퍼파라미터로 데이터 준비 단계 중 일부를 다룰 수 있다는 것을 잊지 마세요. 예를 들어, 그리드 서치(grid search)는 확신할 수 없는 피쳐(feature)를 추가하는 것과는 상관없이 자동적으로 찾아낼 것입니다. 자동으로 간단히 아웃라이어 핸들링, 누락된 피쳐들, 피쳐 선택 등에 대한 최상의 방법을 찾을 수 있도록 사용될 수 있을 것입니다. 


무작위 서치(Randomized Search)

그리드 서치(grid search) 접근법은 앞의 예처럼, 상대적으로 적은 조합을 탐색할 때 좋습니다. 

하지만, 하이퍼파라미터 서치 스페이스가 클때는, 그리드 서치 대신에 RandomizedSearchCV를 사용하는 것을 더 선호합니다. 

이 클래스는 GridSearchCV 클래스와 매우 유사한 방법으로 사용할 수 있습니다. 

하지만 모든 가능한 조합들을 시도하는 대신에, 매 반복시마다 각 하이퍼파라미터에 대해 랜덤한 값을 선택함으로써 주어진 숫자만큼 무작위 조합에 대해 평가합니다. 

이 접근법은 두가지 주요 혜택이 있습니다.

  • 만약 1,000회 반복하도록 무작위 서치를 실행한다면, 이 접근법은 각각의 하이퍼파라미터에 대해 1,000개의 다른 값들을 탐색할 것입니다. (그리드 서치 접근법에서는 각각의 하이퍼파라미터에 대해 단지 몇개의 값들을 탐색)

  • 단히 반복할 숫자를 설정함으로써, 하이퍼파라미터 검색에 할당할 컴퓨팅 자원을 더 잘 컨트럴할 수 있습니다. 


앙상블 메서드(Ensemble Methods)

시스템을 튜닝하기 위한 또 다른 방법은 가잘 잘 수행할 수 있는 모델들을 결합시켜 보는 것입니다. 

그 그룹(또는 "앙상블")은 최상의 개별 모델보다 더 잘 수행할 것입니다(랜덤 포레스트가 의지하는 개별 결정 트리 보다 랜덤 포레스트가 더 잘 수행하는 것과 같음). 

특히, 개별 모델이 매우 다른 형태의 오류를 만드는 경우 더 그렇습니다. 


최고의 모델과 그 모델의 에러 분석하기

가장 좋은 모델을 검사하여 문제에 대한 좋은 통찰을 얻을 수 있습니다. 

예를 들어, RandomForestRegressor은 정확한 예측을 하기 위해, 각 속성의 상대적 중요성을 나타낼 수 있습니다:

>>> feature_importances = grid_search.best_estimator_.feature_importances_

>>> feature_importances

array([  7.14156423e-02,   6.76139189e-02,   4.44260894e-02,

1.66308583e-02,  1.66076861e-02,   1.82402545e-02,

1.63458761e-02,   3.26497987e-01,   6.04365775e-02,

1.13055290e-01,   7.79324766e-02,   1.12166442e-02,

1.53344918e-01,   8.41308969e-05,   2.68483884e-03,

3.46681181e-03])


해당 속성의 이름 옆에 중요도 점수를 표시합시다:


>>> extra_attrivs = ["rooms_per_hhold", "pop_per_hhold", "bedrooms_per_room"]

>>> cat_one_hot_attribs = list(encoder.classes_)

>>> attributes = num_attribs + extra_attribs + cat_one_hot_attribs

>>> sorted(zip(feature_importances, attributes), reverse=True)

[(0.32649798665134971, 'median_income'),

(0.15334491760305854, 'INLAND'),

(0.11305529021187399, 'pop_per_hhold'),

(0.07793247662544775, 'bedrooms_per_room'),

(0.071415642259275158, 'longitude'),

(0.067613918945568688, 'latitude'),

(0.060436577499703222, 'rooms_per_hhold'),

(0.04442608939578685, 'housing_median_age'),

(0.018240254462909437, 'population'),

(0.01663085833886218, 'total_rooms'),

(0.016607686091288865, 'total_bedrooms'),

(0.016345876147580776, 'households'),

(0.011216644219017424, '<1H OCEAN'),

(0.0034668118081117387, 'NEAR OCEAN'),

(0.0026848388432755429, 'NEAR BAY'),

(8.4130896890070617e-05, 'ISLAND')


이 정보를 가지고, 유용하지 않은 피쳐들(features) 일부를 탈락시키고 싶을 수도 있습니다(예,. 분명히 하나의 ocean_proximity 범주만이 정말 유용합니다. 그래서 다른 것들에 대한 탈락을 시도할 수 있습니다).

또한, 시스템에서 발생시키는 특정 에러를 살펴보아야만 합니다. 

그런 다음, 발생 원인을 이해하도록 해야 하고, 그 문제를 어떻게 고칠 수 있는지도 이해해야 합니다(다른 피쳐들을 추가하거나 반대로 불필요한 피쳐들을 제거하고, 아웃라이어를 클리닝 하는 등). 


테스트 셋에서 시스템 평가하기

잠시동안 모델을 조정한 후에, 결국 효율적으로 잘 수행하는 시스템을 갖게 되었습니다. 

이제 최종 모델을 테스트 셋에서 평가해 볼 시간입니다. 

이 프로세스에 있어 특별한 것은 없습니다; 단지 테스트 셋에서 예측변수(predictors)와 레이블을 가져와, 데이터를 변환(fit_transform()이 아니라 transform()을 호출!)하기 위해 full_pipeline을 실행합니다. 그리고, 테스트 셋에서 최종 모델을 평가합니다:


>>> final_model = grid_search.best_estimator_

>>> X_test = strat_test_set.drop("median_house_value", axis=1)

>>> y_test = strat_test_set["median_house_value"].copy()


>>> X_test_prepared = full_pipeline.transform(X_test)

>>> final_predictions = final_model.predict(X_test_prepared)

>>> final_mse = mean_squared_error(y_test, final_predictions)

>>> final_rmse = np.sqrt(final_mse) 

많은 하이퍼파라미터를 튜닝했다면, 성능은 보통 교차 검증(cross-validation)을 사용해 측정한 것보다 조금 나쁠 겁니다

(왜냐하면, 검증 데이터에서 잘 수행되도록 미세 조정되었기 때문에, 알려지지 않은 데이터셋에서는 잘 수행되지 않을 것입니다). 

이 예에서는 그렇지 않습니다만, 이런 경우가 생기면 테스트 셋에서 숫자가 잘 나올 수 있도록 하이퍼파라미터를 조정하는 유혹에 빠지면 안됩니다; 그 개선은 새로운 데이터에 일반화될 것 같지 않기 때문입니다.

이제 프로젝트가 시작되는 시점이 되었습니다: 해결책을 제시하는 것(학습한 것을 강조 표시하고, 무엇이 작동되고 무엇이 안되는지, 어떤 가정들이 만들어 졌는지, 그리고 이 시스템의 한계는 무엇인지), 모든 것을 문서화하고, 분명한 시각화와 쉽게 기억할 수 있는 문구를 가진 멋진 프리젠테이션을 만드는 것이 필요합니다(예,. "중앙 소득은 주택 가격의 가장 중요한 예측 변수 입니다").


7. 시스템 런칭, 모니터링과 유지하

이제 제품화를 위한 솔루션 준비가 필요합니다. 

특히, 제품을 가동함으로써 시스템에 데이터 소스를 입력하고 테스트를 작성하기 위한 준비가 필요합니다.

또한, 시스템을 정기적으로 실제 사용중에 점검할 수 있는 모니터링 코드를 작성하는 것도 필요합니다. 

문제가 생기면 경고도 날려줘야 합니다. 

이것은 갑작스런 작동중단 뿐 아니라, 성능 저하를 잡아내는 데 있어 중요합니다. 

모델은 정기적으로 새로운 데이터로 훈련되지 않으면, 시간이 지남에 따라 모델의 데이터가 "망가지는" 경향이 있기 때문에 매우 일반적입니다.


시스템의 성능을 평가하려면 시스템의 예측을 샘플링하고 그것들을 평가해야 합니다. 이것은 일반적으로 사람의 분석을 요구합니다. 이 분석가들은 현장 전문가일 수도 있고, 크라우드소싱 플랫폼의 작업자일 수도 있습니다(Amazon Mechanical Turk 또는 CrowdFlower 같은). 어느 쪽이든, 사람의 평가 파이프라인을 시스템에 연결해야 합니다. 

또한, 시스템의 입력 데이터 품질을 평가해야 합니다. 

때때로 나쁜 품질 시그널(예., 오작동하는 센서가 무작위 값들을 보내거나, 다른 팀의 결과가 부실해지거나)때문에, 성능이 약간씩 떨어질 것입니다. 

하지만, 시스템 성능 저하에 따른 경고를 받기까지는 딜레이 시간이 걸리 수 있습니다. 

만약 시스템의 입력을 모니터하고 있다면, 이 경고를 더 일찍 잡아낼 수 있습니다. 

특히 입력 모니터링은 온라인 학습 시스템에서 중요합니다.


마지막으로 말할 것은, 일반적으로 새로운 데이터를 가지고 정기적으로 모델을 훈련시키는 것을 원할 것이라는 것입니다.

가능한 한 이 프로세스를 자동화해야 합니다. 

그렇지 않으면, (적어도) 6개월마다 시스템을 고칠 가능성이 큽니다. 

그리고 시스템 성능은 시간이 지남에 따라 크게 변동될 수 있습니다. 

만약 온라인 학습 시스템이라면, 일정한 간격으로 상태 시냅샷을 저장해야만 할 것입니다. 

그렇게 해서, 쉽게 이전의 작동 상태로 되돌아갈 수 있습니다. 


여기까지가 예제를 가지고 학습해 본 머신러닝 프로젝트 실행에 대한 전체 프로세스였습니다. 

여러 번 읽어보고 익혀야 이해가 될 것 같네요. 

앞으로 저도 지금까지 설명한 절차대로 http://kaggle.com과 같은 사이트에서 실습을 진행해 보고 싶습니다.



머신러닝 프로젝트 실행-1

(1~2단계: 1. 문제정의하고 전체 그림 바라보기 / 2. 데이터 얻기바로가기 


머신러닝 프로젝트 실행-2

(3단계: 3. 인사이트를 찾기 위해 데이터 탐색하기바로가기 


머신러닝 프로젝트 실행-3

(4단계: 4. 기본 데이터 패턴을 머신러닝 알고리즘에 더 잘 노출시킬 수 있도록 데이터 준비하기바로가기


머신러닝 프로젝트 실행-4

(5단계: 5. 다양한 모델을 탐색하고 그 중 가장 좋은 모델 찾기바로가기


참고)'Hands-On Machine Learning with Scikit-Learn and TensorFlowchapter 2' 

주피터 노트북에서 볼 수 있는 전체 코드 얻기

반응형

+ Recent posts