ML Process Overview
머신러닝 프로세스의 전체적인 오버뷰를 정리해보았습니다.
1. 문제 정의
[ 비즈니스의 목적 파악 ]
모델을 사용해서 어떤 이익을 얻고자 하는지 비즈니스의 목적을 정확히 파악하는 것이 중요한데, 그에 맞게 다음 내용들을 파악하여야 합니다.
- 문제구성
- 목적에 맞게 활용할 수 있는 알고리즘 선택
- 모델 평가에 사용할 성능 지표 선정
- 모델 튜닝에 자원 및 시간비용을 얼마나 투자할 것인지
[ 기존 솔루션과의 비교 ]
현재 솔루션이 어떻게 구성되어 있는지를 통해 문제 해결방법에 대한 정보를 밴치마킹 할 수 있습니다.
- 과거의 데이터를 어떻게 활용하고 있었는지, 데이터 기반으로 어떻게 모형을 구축했었는지를 통해 개선할 포인트를 탐색
- 기존에 어떤 성능지표를 활용하였는지를 통해 보다 나은 성능 지표 선택 가능
[ 구체적 문제 정의 ]
기존의 어떤 방식으로 문제가 정의되었는지 파악하고 나서, 구체적으로 문제를 다시 한번 정의합니다.
- 지도 vs 비지도 vs 준지도 vs 강화학습?
- 분류 vs 회귀 vs etc?
- 배치학습 vs 온라인 학습?
[ 가정 검사 ]
머신러닝 시스템의 입력 타겟 값으로 새로운 데이터 타겟 값 형태 그대로 들어가도 되는지 확인해야 합니다.
- 범주형 변수로 구성된 시스템에 수치형 데이터를 입력하면 error 발생
- 시스템이 회귀가 아닌 분류 작업으로 구성되어 있는 지를 미리 확인
2. 데이터 추출
[ 데이터 확인 ]
- head() : default로 데이터 앞쪽 5개의 데이터를 추출하며, 괄호안에 숫자를 지정하여 원하는 양만큼 데이터를 확인할 수 있습니다.
- info() : 데이터의 전체 행수, 각 특성의 데이터 타입과 결측치(null)가 아닌 개수를 파악할 수 있습니다
- value_counts() : 특성별로 데이터 분포를 확인할 수 있습니다.
- describe() : 수치형 특성에 대한 기초통계자료를 제시해줍니다.( 평균, 표준편차, 백분위수 등)
- hist() : 전체 데이터셋의 수치형 특성에 대해 히스토그램을 확인할 수 있습니다
[ 테스트 데이터셋 생성 ]
과대적합을 피하기 위해 미리 테스트 데이터를 만들고, 절대로 학습에 이용하지 않아야 합니다. 또한, 테스트 데이터를 들여다 보면, 테스트 데이터가 지닌 패턴에 속아 학습 모델을 선택하게 될 수 있는데, 이러한 낙관적 추정은 이후 실제 시스템을 런칭했을 때 성능저하의 원인(데이터 편향)이 될 수 있기 때문에 테스트 데이터는 미리 보지 않는 것이 좋습니다.
- train_test_split() : sklearn.model_selection의 함수로 훈련데이터(80%) 테스트데이터(20%) 분리
- StratifiedShuffleSplit() : 타겟 비율(계층적 비율)을 훈련/테스트 셋에서 유지하여 분리
[ 데이터 탐색 및 시각화 ]
- 수치형 특성 사이의 상관관계를 표현하는 방법
- corr() : 모든 특성간의 표준 상관계수(피어슨 상관계수)를 쉽게 계산 가능
- scatter_matrix : 각 특성에 대해서는 히스토그램, 다른 특성들과는 산점도 그래프를 그려 상관관계를 파악
3. 데이터 준비
[ 설명변수와 타겟 변수 분리 ]
drop() 메서드를 활용하여 설명변수와 타겟 변수를 분리해줍니다.
# housing : 설명변수
housing = strat_train_set.drop('median_house_value', axis=1)
# housing_labels : 타겟변수('median_house_value')
housing_labels = strat_train_set['median_house_value'].copy()
[ 데이터 정제 ]
결측치(null)이 있는 경우 데이터 정제 과정을 거쳐 수정을 해야 합니다
- dropna() : 해당 null 데이터들을 제거
- drop() : 전체 특성을 제거
- fillna() : null 데이터들을 0/평균값/중앙값 등의 특정 값으로 대체
- SimpleInputer 클래스 : 누락된 값을 중간값으로 쉽게 변형 대체 가능
from sklearn.impute import SimpleImputer
# 전략을 median으로 설정하여 imputer 생성
imputer = SimpleImputer(strategy='median')
# 수치형 변수들에 대해 fit함수 적용하면 변수의 median값들을 가져올 수 있음
imputer.fit(housing_num)
# statistics_를 통해 각 변수별 median 값을 반환하여 확인
imputer.statistics_
# transform 함수를 통해 생성된 imputer을 수치형 변수들에 적용하여 새로운 dataframe X를 생성
X = imputer.transform(housing_num)
[ 범주형 특성 다루기 ]
- OrdinalEncoder 클래스 : 범주형 변수를 수치형 변수로 변환
- OnehotEncoder 클래스 : 범주형 변수를 더미 변수로 변환
- 희소행렬로 출력되므로 toarray()메서드로 numpy.array화 해주어야 함
[ 변수 스케일링 ]
머신러닝 알고리즘 학습 시, 수치형 설명변수들의 스케일이 많이 다르면 학습이 제대로 되지 않는 경우들이 다수 존재하기 때문에, 설명 변수들이 나타내는 값의 범위가 유사하도록 스케일링해야 합니다. 일반 적으로 타겟 변수에 대한 스케일링은 불필요합니다.
- min-max 스케일링(정규화) : 최소값을 뺸 후 최대값과 최소값을 뺸 차로 값들을 나누어 0~1 범위에 속하도록 값을 스케일링
- sklearn의 MinMaxScaler클래스를 통해서 변환가능
- 표준화(Standardization) : 평균을 뺸 후, 표준편차로 나누어, 분포의 평균이0, 분산이1이 되도록 반환
- 이상치의 영향을 덜 받음
- sklearn의 StandardScaler 클래스를 통해서 변환가능
- Pipeline 클래스 : 변수들을 변환하고 스케일해야하는 단계가 많아질 때 fit_transform()을 활용하여 한번에 학습해서 변환
from sklearn.pipeline import Pipeline
num_pipeline = Pipeline([
('imputer', SimpleImputer(strategy='median')),
('std_scaler', StandardScaler()),
])
housing_num_tr = num_pipeline.fit_transform(housing_num)
- ColumnTransformer클래스 : 범주형 변수와 수치형 변수를 동시에 하나의 변환기로 처리
from sklearn.compose import ColumnTransformer
num_attribs = list(housing_num) # 수치형 변수
cat_attribs = ['ocean_proximity'] # 범주형 변수
full_pipeline = ColumnTransformer([
('num', num_pipeline, num_attribs),
('cat', OneHotEncoder(), cat_attribs),
])
housing_prepared = full_pipeline.fit_transform(housing)
4. 모형 선택 및 훈련
훈련데이터셋을 활용하여 여러 모형으로 훈련하고, 성능 지표를 통해 예측값과 실제값 비교하여 모형을 평가합니다.
[ 교차 검증 ]
만약 예측 오차가 0이라면 과대적합되었음을 의미하는데, 이를 해결하기 위해 교차 검증을 사용합니다. 다양한 고도화 알고리즘 및 규제 방법들을 기반으로 과대적합이 되지 않으면서, 예측력이 높은 모델을 찾는 것이 중요합니다.
- K-fold 교차 검증
from sklearn.model_selection import cross_val_score
scores = cross_val_score(tree_reg, housing_prepared, housing_labels,
scoring='neg_mean_squared_error', # mse를 음수로 반환
cv=10) # 10번의 교차검증 시행
5. 모델 튜닝
[ 그리드 탐색 ]
알고리즘 내 효과적인 하이퍼파라미터 조합을 찾을 때까지, 탐색하고자 하는 하이퍼파라미터와 그에 해당하는 시도해볼 값들을 지저하여 하이퍼파라미터 튜닝을 진행하는 것입니다.
- GridSearchCV 클래스 : 미리 설정한 하이퍼파라미터 조합에 대해 교차 검증을 진행하고, 이를 통해 평가
from sklearn.model_selection import GridSearchCV
# 그리드 탐색 정의
param_grid = [
# 3X4개의 하이퍼파라미터 튜닝
{'n_estimators':[3,10,30], 'max_features':[2,4,6,8]},
# 또 다른 2X3개의 하이퍼파라미터 튜닝방법을 설정할 수 있음
{'bootstrap':[False], 'n_estimators':[3,10], 'max_features':[2,3,4]},
]
forest_reg = RandomForestRegressor(random_state=42)
grid_search = GridSearchCV(forest_reg, param_grid, cv=5, # 교차검증 5회 진행
scoring='neg_mean_squared_error',
return_train_score=True)
# 따라서, ((3*4)+(2*3))*5 = 총 90번 학습 진행
grid_search.fit(housing_prepared, housing_labels)
grid_search.best_params_
'''
{'max_features': 8, 'n_estimators': 30}
'''
[ 랜덤 탐색 ]
GridSearchCV를 진행할 하이퍼파라미터 조합의 수가 너무 많을 때 사용하는 탐색 방법입니다.
- RandomizedSearchCV 클래스 : 조합 내에서 임의의 하이퍼파라미터를 대입하여 지정한 횟수만큼 평가
- 랜덤 탐색 1000회 반복하면, 각 하이퍼파라미터마다 각기 다른 1000개 경우를 탐색할 수 있음
- 반복 횟수를 단순히 조절하는 것 만으로도 하이퍼파라미터에 투입할 컴퓨팅자원을 제어할 수 있음
from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import randint
param_distribs = {
'n_estimators':randint(low=1, high=200),
'max_features':randint(low=1, high=8),
}
forest_reg = RandomForestRegressor(random_state=42)
rnd_search = RandomizedSearchCV(forest_reg, param_distributions=param_distribs,
n_iter=10, cv=5, scoring='neg_mean_squared_error', random_state=42)
rnd_search.fit(housing_prepared, housing_labels)
cvres = rnd_search.cv_results_
for mean_score, params in zip(cvres['mean_test_score'], cvres['params']):
print(np.sqrt(-mean_score), params)
'''
49121.49837525519 {'max_features': 7, 'n_estimators': 180}
51272.09460120037 {'max_features': 5, 'n_estimators': 15}
50535.37125677256 {'max_features': 3, 'n_estimators': 72}
50689.968708041284 {'max_features': 5, 'n_estimators': 21}
49129.57573326101 {'max_features': 7, 'n_estimators': 122}
50491.86588833997 {'max_features': 3, 'n_estimators': 75}
50414.569062947536 {'max_features': 3, 'n_estimators': 88}
49462.00096652969 {'max_features': 5, 'n_estimators': 100}
50200.230149209325 {'max_features': 3, 'n_estimators': 150}
64800.37553997819 {'max_features': 5, 'n_estimators': 2}
'''
[ 테스트 데이터로 시스템 평가 ]
설명변수와 타겟변수를 분리하고 훈련에서 쓰인 변환 파이프라인을 통해 transform을 진행합니다. (훈련에서는 fit_transform을 사용하였는데, 테스트 데이터로 시스템을 평가할 때는 학습 과정이 포함된 변환은 진행하지 않아야하기 때문에 transform을 사용한다는 것을 유의해야합니다.) 이후, 예측값과 실제값을 비교하여 평가를 진행합니다.
[ 신뢰 구간 ]
예측값과 실제값의 오차를 단일 추정값으로 확인하는 것이 아니라, 얼마나 정확한 지를 95% 신뢰 구간 계산을 통해 점검해볼 수 있습니다.
- Scipy.stats.t.interval()
from scipy import stats
confidence = 0.95
squared_errors = (final_predictions - y_test)**2
np.sqrt(stats.t.interval(confidence, len(squared_errors)-1,
loc=squared_errors.mean(),
scale=stats.sem(squared_errors)))
'''
array([45909.04350565, 49733.6072416 ])
'''
6. 런칭, 모니터링, 시스템 유지보수
[ 런칭(디플로잉) ]
- 서비스 제품 시스템에 모형을 적용하기 위한 준비를 진행
- 훈련된 모형을 Joblib 패키지를 활용하여 저장 후, 상용 환경에서 로딩 후 predict() 메서드 기반의 예측 모듈 생성
- 웹 서비스에서 버튼을 누르면, predict() 메서드가 호출되도록 개발
[ 모니터링 ]
- 일정 간격으로 시스템 내 모형의 실시간 성능을 구체적인 지표를 통해 확인
- 성능이 떨어졌을 때, 알람을 통지할 수 있는 모니터링 코드 작성 필요
- 갑작스러운 급격한 성능 감소 뿐만 아니라, 눈에 띄지 않게 장기적으로 서서히 성능이 감소하는 경우도 감지해야함
- 제품 결함을 사람이 분석 및 평가하기 우해 수시로 전문가에게 불확실한 수준의 데이터 전송
- 데이터의 결함이 없는지, 변화가 있는지 확인
- 정기적으로 새로운 데이터를 수집하여 조사원을 활용해 타겟 변수 labeling 진행
- 데이터셋 업데이트 후, 정기적으로 모형 재훈련 진행 및 배포
- 재훈련 후 성능이 개선되면, 새로운 모형을 제품에 배포 및 기존 모형을 백업
[ 시스템 유지보수 ]
- 데이터셋 업데이트 후, 정기적으로 모형 재훈련 진행 및 배포
- 재훈련 후 성능이 개선되면, 새로운 모형을 제품에 배포 및 기존 모형을 백업
- 모든 모형은 백입이 되도록 환경 구축
- 올바르지 않게 모형이 작동하는 경우, 이전 모형으로 빠르게 롤백할 수 있도록 절차와 도구를 준비
- 데이터셋 또한 백업이 되도록 환경 구축
- 새로운 데이터셋이 이상치로 가득차 있다고 판명되는 경우와 같이 새로운 데이터셋이 오염되었을 시, 이전 데이터를 활용하여 평가 진행
https://github.com/sonzwon/TIL_DL/blob/master/ML_Process.ipynb
GitHub - sonzwon/TIL_DL
Contribute to sonzwon/TIL_DL development by creating an account on GitHub.
github.com
깃허브 주소를 참고하면 ML process의 전반적인 내용을 이해하는데에 도움이 될 것 입니다.