패러미터 최적화
패러미터 탐색
| 기법 | Random Search | Grid Search | Bayesian Opt. |
|---|---|---|---|
| 원리 | 지정된 분포에서 무작위 샘플링 | 모든 조합을 격자 형태로 전수 조사, 주로 교차 검증과 함께 사용 | 가우시안 프로세스 등으로 확률적 모델링 |
| 장점 | 불필요한 연산 감소, Grid Search보다 빠름 | 전역 최적점 보장 (충분한 격자 시) | 적은 시도로 최적해 도달 가능 |
| 단점 | 지역 최적점에 빠질 가능성 있음 | 연산 비용 매우 높음, 차원의 저주 | 순차적 계산 필요 (병렬화 어려움) |
| 파라미터 정의 방식 | dict (분포 또는 List 형태) | dict (List 형태의 고정값) | dict (Space 객체: Integer, Real 등) |
| 주요 라이브러리 | sklearn.model_selection | sklearn.model_selection | skopt (BayesSearchCV) |
Random Search
from sklearn.model_selection import RandomizedSearchCV
if 'hparam 후보군':
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier()
param_dist = {
'n_estimators': np.random.randint(10, 100),
'max_depth': [None, 10, 20, 30]
}
if '탐색':
# 10(n_iter) × 5(cv) = 총 50번의 학습 수행
random_search = RandomizedSearchCV(estimator=model
, param_distributions=param_dist
, n_iter=10
, cv=5 # 교차검증
)
random_search.fit(X_train, y_train)
if '확정, 사용':
'''
random_search.best_params_ # 최적 하이퍼파라미터
random_search.cv_results_ # 교차 검증 결과
'''
# 최적모델로 예측
best_model = random_search.best_estimator_
best_model.predict(X_test)
Gridsearch
-
초기 탐색: 파라미터 범위를 잘 모를 때는 아래 코드처럼 RandomizedSearchCV로 넓게 훑어라.
-
정밀 타격: 랜덤 서치에서 좋은 범위가 확인되면, 위 코드처럼 GridSearchCV를 사용해 그 주변 값들을 촘촘하게 검증하는 것이 정석이다.
-
코드 완성도: 위 코드는 predict까지 포함된 전체 파이프라인을 보여주지만, 아래 코드는 단순한 객체 생성 예시에 불과하다. 실제 적용 시에는 아래 코드에도 fit과 predict 과정을 추가해야 한다.
from sklearn.model_selection import GridSearchCV
if 'hparam 후보군':
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier()
param_grid = {
'n_estimators': [10, 50, 100],
'max_depth': [None, 10, 20, 30]
}
if '탐색':
# 3(n_estimators) × 4(max_depth) × 5(cv) = 총 60번의 학습 수행.
grid_search = GridSearchCV(estimator=model
, param_grid=param_grid
, cv=5 # 교차검증
)
grid_search.fit(X_train, y_train)
if '확정, 사용':
best_model = grid_search.best_estimator_ # 최적 모델
best_model.predict(X_test)
pipeline 을 활용한 서치
| 구성 요소 | 파라미터 예시 | 설명 |
|---|---|---|
| PCA | pca__n_components | 차원 축소 후 유지할 주성분의 개수 선택 |
| Logistic | model__C | 규제 강도의 역수 (). 작을수록 강한 규제 적용 |
| Poisson | model__alpha | L2 규제 강도. 클수록 가중치 감소 효과 증대 |
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.linear_model import LogisticRegression, PoissonRegressor
# 모델별 탐색 공간 정의 (단계명__파라미터명 형식)
param_grids = {
'LogisticRegression': {
'pca__n_components': [2, 5, 10],
'model__C': [0.1, 1.0, 10.0],
'model__penalty': ['l2']
},
'PoissonRegressor': {
'pca__n_components': [2, 5, 10],
'model__alpha': [0.1, 1.0, 10.0],
'model__max_iter': [1000]
}
}
models = [LogisticRegression(), PoissonRegressor()]
for curr_model in models:
model_name = curr_model.__class__.__name__
# 파이프라인 구성
pipe = Pipeline([
('scaler', StandardScaler()),
('pca', PCA()),
('model', curr_model)
])
# GridSearchCV 적용
grid_search = GridSearchCV(
estimator=pipe,
param_grid=param_grids[model_name],
cv=5,
scoring='neg_mean_squared_error' if model_name == 'PoissonRegressor' else 'accuracy',
n_jobs=-1
)
grid_search.fit(X_train, y_train)
print(f"Best Params ({model_name}): {grid_search.best_params_}")
best_model = grid_search.best_estimator_
predictions = best_model.predict(X_test)Bayesian Optimization
from hyperopt import hp, fmin, tpe, Trials, STATUS_OK, space_eval
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
import numpy as np
# 1. 탐색 공간(Search Space) 정의
# hp.quniform: 정수형 파라미터(범위 시작, 끝, 간격)
# hp.choice: 범주형 파라미터
space = {
'n_estimators': hp.quniform('n_estimators', 50, 200, 10),
'max_depth': hp.quniform('max_depth', 5, 30, 1),
'min_samples_split': hp.quniform('min_samples_split', 2, 20, 1),
'criterion': hp.choice('criterion', ['gini', 'entropy'])
}
# 2. 목적 함수(Objective Function) 정의
def objective(params):
# n_estimators 등 실수로 반환되는 값을 int로 형변환 필수
model = RandomForestClassifier(
n_estimators=int(params['n_estimators']),
max_depth=int(params['max_depth']),
min_samples_split=int(params['min_samples_split']),
criterion=params['criterion'],
random_state=42,
n_jobs=-1
)
# 교차 검증 수행 (hyperopt는 최소화를 수행하므로 Accuracy에 -1을 곱함)
score = cross_val_score(model, X_train, y_train, cv=5, scoring='accuracy').mean()
return {'loss': -score, 'status': STATUS_OK}
# 3. 최적화 실행
trials = Trials() # 시도 기록 저장 객체
best = fmin(
fn=objective,
space=space,
algo=tpe.suggest, # TPE 알고리즘 적용
max_evals=30, # 시도 횟수
trials=trials,
rstate=np.random.default_rng(42) # 결과 재현을 위한 시드 설정
)
# 4. 결과 출력
print("\n최적의 하이퍼파라미터 (인덱스 포함):", best)
# hp.choice로 넘긴 인덱스 값을 실제 값으로 변환
best_resolved = space_eval(space, best)
print("최종 변환된 파라미터:", best_resolved)'''
import sys
import joblib
sys.modules['sklearn.externals.joblib'] = joblib
from skopt import BayesSearchCV
from skopt.space import Real, Categorical, Integer
# 1. 탐색 공간(Search Space) 정의
# GridSearchCV와 달리 '범위'를 지정할 수 있음
search_spaces = {
'pca__n_components': Integer(2, 5), # 2에서 5 사이 정수 탐색
'classifier__n_estimators': Integer(50, 200), # 50에서 200 사이 정수 탐색
'classifier__max_depth': Integer(3, 15), # 3에서 15 사이 정수 탐색
'classifier__criterion': Categorical(['gini', 'entropy']) # 범주형 변수
}
# 2. BayesSearchCV 설정
bayes_search = BayesSearchCV(
estimator=full_pipeline,
search_spaces=search_spaces,
n_iter=32, # 총 반복 횟수 (예산)
cv=5,
n_jobs=-1,
random_state=42,
scoring='accuracy'
)
# 3. 최적화 실행
# bayes_search.fit(X_train, y_train)
'''