AI SCHOOL

[ML] GridSearch / GradientBoostingRegressor

moru_xz 2023. 3. 19. 00:09
  • label smoothing

모델이 과적합되는 것을 방지하고 일반화 능력을 향상시키는 데 도움

- 학습 속도를 늦추는 단점

train['count_log1p'] = np.log1p(train['count'])

# 되돌릴 때 
train['count_expm1'] = np.exp(train['count_log1p']) - 1

train[['count', 'count_log1p', 'count_expm1']].hist(bins = 50, figsize = (12, 4))

 

  • GradientBoostingRegressor

- 앙상블 학습 방법 중 하나

- 초기 예측값을 생성한 후, 이를 통해 잔여 오차를 계산하여 이를 예측 모델에 추가로 학습시키는 방법을 사용

- 마치 오답노트를 공부하는 것과 비슷

from sklearn.ensemble import GradientBoostingRegressor

model = GradientBoostingRegressor(random_state=42)
model

 

  • GridSearchCV

- 하이퍼파라미터의 모든 가능한 조합을 시도하여 최적의 조합을 찾아내는 방법

- 가능한 모든 조합을 시도하기 때문에 매우 시간이 오래 걸리지만, 상대적으로 단순하고 직관적인 방법

- Random Search와 같은 다른 방법을 사용하여, 무작위로 몇 개의 하이퍼파라미터를 선택하고 이를 테스트하는 것이 가능 

- but, Grid Search보다 더 빠르지만, 최적의 하이퍼파라미터를 찾지 못할 수도 있음

parameters = {"n_estimators": (200, 300, 400),
             "learning_rate":(0.05, 0.1, 0.2)}

import sklearn
sklearn.metrics.SCORERS.keys()

from sklearn.model_selection import GridSearchCV
reg = GridSearchCV(model, parameters, n_jobs=-1, cv=3, verbose=2,
                   scoring="neg_root_mean_squared_error")
reg.fit(X_train, y_train)

 


 

데이터셋 확인 및 전처리

base_path = "data/bike"
train = pd.read_csv(f"{base_path}/train.csv")
test = pd.read_csv(f"{base_path}/test.csv")
train["datetime"] = pd.to_datetime(train["datetime"])
train["year"] = train["datetime"].dt.year
train["month"] = train["datetime"].dt.month
train["day"] = train["datetime"].dt.day
train["hour"] = train["datetime"].dt.hour
train["minute"] = train["datetime"].dt.minute
train["second"] = train["datetime"].dt.second
train["dayofweek"] = train["datetime"].dt.dayofweek

#test 데이터도 똑같이

 

EDA

train['count_log1p'] = np.log1p(train['count'])
train['count_expm1'] = np.exp(train['count_log1p']) - 1
train[['count', 'count_log1p', 'count_expm1']].hist(bins = 50, figsize = (12, 4))

train[['count', 'count_log1p', 'count_expm1']].describe()

❓ Log Transformation(label smoothing)

- log를 count값에 적용하게 되면 한쪽에 너무 뾰족하게 있던 분포가 좀 더 완만한 분포가 된다.
- 어떤 쪽으로 너무 치우치거나 뾰족한 데이터가 완만하게 된다.
- 정규분포에 좀 더 가까운 형태로 만들어준다.
- log를 취한 값을 사용하게 되면 이상치에도 영향을 덜 받는다.
- 1을 더해주는 이유는 1보다 작은 값에서 음수를 갖기 때문에 가장 작은 값인 1을 더해서 음수가 나오지 않게 처리할 수 있다.
- np.log로 로그를 취했던 값을 다시 원래의 값으로 복원할 수 있다.
- log 값으로 예측한 값을 원래대로 돌려놓는 것 -> 제출할 때

 

학습, 예측 데이터셋 나누기

label_name = 'count'
feature_names = ['season', 'holiday', 'workingday', 'weather', 'temp',
       'atemp', 'humidity', 'windspeed', 'year', 'hour', 'dayofweek']
       
X_train = train[feature_names]
X_test = test[feature_names]

y_train = np.log1p(train[label_name])

 

GradientBoostingRegressor 와 GridSearchCV

from sklearn.ensemble import GradientBoostingRegressor
model = GradientBoostingRegressor(random_state = 42)
model

parameters = {'n_estimators': (200, 300, 400), 
              'learning_rate': (0.05, 0.1, 0.2)}
              
from sklearn.model_selection import GridSearchCV

reg = GridSearchCV(model, parameters, n_jobs = -1, cv = 3, verbose = 2, 
                   scoring = 'neg_root_mean_squared_error')
reg.fit(X_train, y_train)

- metric 기본값, 분류 : accuracy / 회귀 : r square score -> scoring으로 지정 가능

- 'neg_root_mean_squared_error' -> 로그 두 번 씌우지 않으려고 RMSE 사용 

-> 'neg' = 어떤 측정 지표는 클 수록 좋은 값이고 어떤 측정지표는 작을 수록 좋은 값인데, 기준을 통일하기 위해 작을수록 좋은 측정지표에 음수를 취해주게 되면 클 수록 좋은 지표와 같게 평가할 수 있기 때문

best_model = reg.best_estimator_ ;
best_model

 

-> 최고 점수 확인

 

pd.DataFrame(reg.cv_results_).sort_values('rank_test_score')

-> 'cv=3' 해서 split의 수가 3개가 나오고 그것들의 평균인 'mean_test_score' 가 가장 높은 것의 파라미터가 GridSearchCV로 얻은 최적의 하이퍼 파라미터

 

  • 직접 구해보고 싶다면

- cross_val_predict 를 통해 얻을 수 있음

from sklearn.model_selection import cross_val_predict
y_valid_predict = cross_val_predict(best_model, X_train, y_train, cv=3, n_jobs=-1, verbose=2)
y_valid_predict[:5]

 

평가

# MSE
((np.expm1(y_train) - np.expm1(y_valid_predict)) ** 2).mean()

#RMSE -> 여기서는 RMSE가 곧 RMLSE => label에 log 해놨기 때문
rmsle = ((y_train - y_valid_predict) ** 2).mean() **0.5

 

학습과 예측

y_predict = model.fit(X_train, y_train).predict(X_test)
y_predict = np.expm1(y_predict) #원래값으로
y_predict[:5]