본문 바로가기
데이터분석

RMSE, Grid Search python 구현

by 블쭌 2020. 11. 12.
728x90
  • RMSE
# RMSE 공식을 구현한 함수를 생성합니다.
# 이 함수는 예측값(predict)과 정답(actual)을 인자로 받습니다.
def rmse(predict, actual):
    # predict와 actual을 numpy array로 변환합니다.
    # 이렇게 하면 수학 연산을 편하게 할 수 있습니다.
    predict = np.array(predict)
    actual = np.array(actual)

    # 공식에 쓰여진대로 predict와 actual을 빼서 차이를 구합니다.
    # 이 차이를 distance라는 이름의 새로운 변수에 할당합니다.
    distance = predict - actual
    
    # 공식에 쓰여진대로 distance를 제곱합니다.
    # 이 결과를 square_distance라는 이름의 새로운 변수에 할당합니다.
    square_distance = distance ** 2
    
    # 공식에 쓰여진대로 square_distance의 평균을 구합니다.
    # 이 결과를 mean_square_distance라는 이름의 새로운 변수에 할당합니다.
    mean_square_distance = square_distance.mean()
    
    # 공식에 쓰여진대로 mean_square_distance에 루트(sqrt)를 씌웁니다.
    # 이 결과를 score라는 이름의 새로운 변수에 할당합니다.
    score = np.sqrt(mean_square_distance)
    
    # score 변수를 반환합니다.
    return score


# scikit-learn의 make_scorer를 활용하여
# rmse 함수를 scikit-learn의 다른 함수에서 사용할 수 있도록 변환합니다.
# 이 결과를 rmse_score라는 이름의 새로운 변수에 할당합니다.
rmse_score = make_scorer(rmse)
rmse_score

  • Grid Search
# 랜덤 서치를 반복할 횟수입니다.
# 보통 100번을 반복합니다.
num_epoch = 100

# hyperparameter 탐색 결과를 리스트로 저장합니다.
coarse_hyperparameters_list = []

# num_epoch 횟수만큼 랜덤 서치를 반복합니다.
for epoch in tqdm(range(num_epoch)):
    # 10에서 100 사이의 정수형(int) 값을 랜덤하게 생성하여 n_estimators 변수에 할당합니다.
    n_estimators = np.random.randint(low=20, high=100)

    # 2에서 100 사이의 정수형(int) 값을 랜덤하게 생성하여 max_depth 변수에 할당합니다.
    max_depth = np.random.randint(low=2, high=10)

    # 1.0에서 1-e10(10의 -10승)사이의 실수형(float) 값을 랜덤하게 생성하여  learning_rate 변수에 할당합니다.
    learning_rate = 10 ** -np.random.uniform(low=1, high=3)

    # 0.1에서 1.0사이의 실수형(float) 값을 랜덤하게 생성하여 subsample 변수에 할당합니다.
    subsample = np.random.uniform(low=0.1, high=1.0)

    # 0.4에서 1.0사이의 실수형(float) 값을 랜덤하게 생성하여 colsample_bytree 변수에 할당합니다.
    colsample_bytree = np.random.uniform(low=0.4, high=1.0)

    # 0.4에서 1.0사이의 실수형(float) 값을 랜덤하게 생성하여 colsample_bylevel 변수에 할당합니다.
    colsample_bylevel = np.random.uniform(low=0.4, high=1.0)

    # XGBRegressor를 생성합니다. 실행할때는 다음의 옵션이 들어갑니다.
    # 1) n_estimators. 트리의 갯수입니다. 지정한 갯수만큼 트리를 생성합니다.
    # 2) max_depth. 트리의 깊이입니다. 지정한 숫자만큼 트리가 깊게 가지를 뻗습니다.
    # 3) learning_rate. 각 트리마다의 비중을 나타냅니다. 너무 작으면 과적합(overfitting)될 가능성이 있고, 너무 높으면 부적합(underfitting)될 가능성이 있습니다.
    # 4) subsample. 하나의 트리를 만들 때 사용할 데이터의 비율을 나타냅니다. 0.0 ~ 1.0 사이의 값을 넣으면 지정한 비율만큼만 랜덤하게 데이터를 사용합니다.
    # 5) colsample_bytree. 하나의 트리를 만들 때 사용할 feature의 비율을 나타냅니다. 0.0 ~ 1.0 사이의 값을 넣으면 트리를 만들 때 지정한 비율만큼만 랜덤하게 feature를 사용합니다.
    # 6) colsample_bylevel. 트리가 한 번 가지를 칠 때 사용할 feature의 비율을 나타냅니다. 0.0 ~ 1.0 사이의 값을 넣으면 트리가 가지를 칠 때 지정한 비율만큼만 랜덤하게 feature를 사용합니다.
    # 생성한 XGBRegressor를 model이라는 이름의 변수에 대입합니다.
    model = MultiOutputRegressor(lgb.LGBMRegressor(n_jobs=-1, random_state=303,
                                                   max_depth=max_depth,
                                                   learning_rate=learning_rate,
                                                   subsample=subsample,
                                                   colsample_bylevel=colsample_bylevel,
                                                   colsample_bytree=colsample_bytree,
                                                   seed=303))

    # cross_val_score를 실행합니다. 실행할 때는 다음의 옵션이 들어갑니다.
    # 1) model. 점수를 측정할 머신러닝 모델이 들어갑니다.
    # 2) X_train. train 데이터의 feature 입니다.
    # 3) y_train. train 데이터의 label 입니다.
    # 4) cv. Cross Validation에서 데이터를 조각낼(split) 갯수입니다. 총 20조각을 내야하기 때문에 20을 대입합니다.
    # 5) scoring. 점수를 측정할 공식입니다. 앞서 구현한 RMSE를 적용합니다.
    # 마지막으로, 이 함수의 실행 결과의 평균(mean)을 구한 뒤 score라는 이름의 새로운 변수에 할당합니다.
    score = cross_val_score(model, train_df, target_df, cv=20, scoring=rmse_score).mean()
    
    # hyperparameter 탐색 결과를 딕셔너리화 합니다.
    hyperparameters = {
        'epoch': epoch,
        'score': score,
        'n_estimators': n_estimators,
        'max_depth': max_depth,
        'learning_rate': learning_rate,
        'subsample': subsample,
        'colsample_bylevel': colsample_bylevel,
        'colsample_bytree': colsample_bytree,
    }

    # hyperparameter 탐색 결과를 리스트에 저장합니다.
    coarse_hyperparameters_list.append(hyperparameters)

    # hyperparameter 탐색 결과를 출력합니다.
    print(f"{epoch:2} n_estimators = {n_estimators}, max_depth = {max_depth:2}, learning_rate = {learning_rate:.10f}, subsample = {subsample:.6f}, colsample_bylevel = {colsample_bylevel:.6f}, colsample_bytree = {colsample_bytree:.6f}, Score = {score:.5f}")


# coarse_hyperparameters_list를 Pandas의 DataFrame으로 변환합니다.
coarse_hyperparameters_list = pd.DataFrame.from_dict(coarse_hyperparameters_list)

# 변환한 coarse_hyperparameters_list를 score가 낮은 순으로 정렬합니다.
# (RMSE는 score가 낮을 수록 더 정확도가 높다고 가정합니다)
coarse_hyperparameters_list = coarse_hyperparameters_list.sort_values(by="score")

# coarse_hyperparameters_list 변수에 할당된 데이터의 행렬 사이즈를 출력합니다.
# 출력은 (row, column) 으로 표시됩니다.
print(coarse_hyperparameters_list.shape)

# coarse_hyperparameters_list의 상위 10개를 출력합니다.
coarse_hyperparameters_list.head(10)
728x90

'데이터분석' 카테고리의 다른 글

Linear Regression Gradient Descent  (0) 2020.12.30
Logistic Regression  (0) 2020.11.12
seaborn 시각화 python  (0) 2020.11.12
데이터 전처리 python  (0) 2020.11.12
python 복사 단순 객체복사 vs shallow copy vs deep copy  (0) 2020.10.19

댓글