패러미터 최적화

패러미터 탐색

기법Random SearchGrid SearchBayesian Opt.
원리지정된 분포에서 무작위 샘플링모든 조합을 격자 형태로 전수 조사, 주로 교차 검증과 함께 사용가우시안 프로세스 등으로 확률적 모델링
장점불필요한 연산 감소, Grid Search보다 빠름전역 최적점 보장 (충분한 격자 시)적은 시도로 최적해 도달 가능
단점지역 최적점에 빠질 가능성 있음연산 비용 매우 높음, 차원의 저주순차적 계산 필요 (병렬화 어려움)
파라미터 정의 방식dict (분포 또는 List 형태)dict (List 형태의 고정값)dict (Space 객체: Integer, Real 등)
주요 라이브러리sklearn.model_selectionsklearn.model_selectionskopt (BayesSearchCV)
 
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 을 활용한 서치
구성 요소파라미터 예시설명
PCApca__n_components차원 축소 후 유지할 주성분의 개수 선택
Logisticmodel__C규제 강도의 역수 (). 작을수록 강한 규제 적용
Poissonmodel__alphaL2 규제 강도. 클수록 가중치 감소 효과 증대
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)
'''