심심해서 하는 블로그 :: '기계학습' 태그의 글 목록

'기계학습'에 해당되는 글 3건

하이퍼파라미터 최적화.. 중요한 건 알겠는데.. 일일히 하는게 번거롭네?


하이퍼파라미터의 최적화는 기계학습의 중요한 태스크 중에 하나입니다.

하이퍼파라미터를 어떻게 선택하는 가에 따라 Overfit 이 된 모델이 될 수 도 있고, Underfit 모델이 될 수 있습니다.

하지만 같은 종류의 모델을 사용하더라도 학습하는 데이터에 따라서 하이퍼파라미터의 값은 상이합니다.


우리는 최적화된 파라미터를 찾기 위해서 값을 조정하면서, 모델을 수행을 하고 모델을 검증을 합니다.

그리고 이걸 결과가 좋을 때까지 하이퍼 파라미터 값을 재변경해서 다시 학습 및 검증을 하는 과정을 반복합니다.

근데 이 과정이 생각보다 귀찮습니다.


Optuna : 하이퍼파라미터 최적화 프레임워크

Optuna는 하이퍼파라미터 최적화 태스크를 도와주는 프레임워크입니다.

파라미터의 범위를 지정해주거나, 파라미터가 될 수 있는 목록을 설정하면 매 Trial 마다 파라미터를 변경하면서, 최적의 파라미터를 찾습니다.


하이퍼파라미터의 범위나 목록은 아래의 방법으로 설정할 수 있습니다.


  • suggest_int : 범위 내의 정수형 값을 선택합니다.

n_estimators = trial.suggest_int('n_estimators',100,500)

  • suggest_categorical : List 내의 데이터 중 선택을 합니다.

criterion = trial.suggest_categorical('criterion' ,['gini', 'entropy'])

  • suggest_uniform : 범위 내의 균일 분포를 값으로 선택합니다.

subsample = trial.suggest_uniform('subsample' ,0.2,0.8)

  • suggest_discrete_uniform : 범위 내의 이산 균등 분포를 값으로 선택합니다.

max_features = trial.suggest_discrete_uniform('max_features', 0.05,1,0.05)

  • suggest_loguniform : 범위 내의 로그 함수 선상의 값을 선택합니다.

learning_rate = trial.sugget_loguniform('learning_rate' : 1e-6, 1e-3)

 

소스 코드

이전 포스팅에서 사용했던 XGBoost Regressor를 최적화 하는데 사용한 소스코드 입니다.

전체 소스코드는 https://www.kaggle.com/ssooni/xgboost-lgbm-optuna 를 참고하시면 됩니다.


매 Trial 마다 수행할 함수를 작성합니다.

함수 내부에는 하이퍼파라미터의 값을 정의하는 부분과 모델을 학습하는 부분을 작성하고 Loss Metric의 결과를 반환합니다.



이제 아래의 소스를 참고해서 optuna를 사용해서 최적의 파라미터를 찾아봅시다.

최적의 파라미터는 study.best_trial.params 에 저장되어 있습니다.



optuna는 추가적으로 학습하는 절차를 확인할 수 있는 시각화 툴도 제공합니다.

다양한 시각화 기법을 제공하지만 저는 매 Trial 마다 Loss가 어떻게 감소되었는 확인 할 수 있는 함수와

하이퍼 파라미터 별로 중요도를 확인할 수 있는 함수를 소개 합니다.



도움이 되셨으면, 아래의 공감 버튼을 눌러주세요.

공감 버튼은 작성자에게 큰 동기부여가 됩니다.

,

캐글에서 사랑받는 XGBoost

요즘 캐글에서 문제를 도전해보는 재미로 공부를 하고 있습니다.

최근에는 Tabular Playground Series - Jan 2021[ kaggle.com/c/tabular-playground-series-jan-2021 ] 를 푸는 중에 다른 사람들이 올려놓은 노트북을 참고 해보니,

대부분이 XGBoost를 사용해서 문제를 풀고 있는 것을 확인 했습니다.

왜 이렇게 사랑 받고 있는지 궁금해서 직접 사용해보고 느낀 점을 정리해서 포스팅 해보곘습니다.


앙상블 기법 : Boosting

그 전에 XGBoost에서 사용하는 Boosting이라는 앙상블 기법에 대해서 간단하게 설명을 해보겠습니다.

앙상블은 직관적으로 "집단 지성" 이라고 생각을 하면 편리합니다. 여러 개의 모델을 사용해서 각각의 예측 결과를 만들고 그 예측 결과를 기반으로 최종 예측결과를 정하는 방법이죠


그 중 Boosting이란 방법은 비교적 약한 모델들을 결합하여 하나의 강한 모델 만드는 과정입니다.

모델 A이 예측한 결과를 다음 모델인 B에서 보완하여 예측하고 최종적으로 C에서 보완을 해서 예측 결과를 만들어 내는 방식이죠.

Boosting을 사용하는 대표적인 모델은 AdaBoost, Gradient Boost 등등이 이 있고 XGBoost는 그 중 Gradient Boosting 을 사용해서 모델링을 합니다.


Gradient Boosting 설명을 수학없이 간결하게 해준 유튜브 영상이 있어서 링크를 남겨 둘게요.

이거보다 설명 잘 할 수 없을거 같아요. 꼭 보세요. 두 번 보세요.

https://www.youtube.com/watch?v=3CC4N4z3GJc


XGBoost : Extreme Gradient Boosting

장점 : 계산 속도 향상, Kaggle에서 수차례 우승한 경력

sklearn 에도 Gradient Boosting 로 Regression 또는 Classification 을 할 수 있는 매소드를 제공하고 있습니다만, 시간이 너무 오래 걸립니다.

하지만 XGBoost의 경우에는 병렬 연산을 지원하여 계산 속도를 향상 시킵니다.

또한 GPU를 사용 할 수 있는 옵션을 제공하기 때문에 학습하는데 소요되는 시간을 절약할 수 있습니다.

이것은 하이퍼파라미터 튜닝을 할 때도 특히 빛이 납니다. (CPU 만으로 50회를 돌리다 하루가 넘게 소요되서 당황스러웠던 기억이 있습니다.)

 

XGBoost는 Overfitting 을 Overfitting 을 제어 하기 위해 두 가지 방법을 제안합니다.

1. 모델의 복잡도를 제어하는 방법 : max_depth, min_child_weight, gamma 하이퍼파라미터 사용

2. 다음 모델로 Loss 를 전달할 때 Random Value를 추가하는 방법 : subsample, colsample_bytree 파라미터 사용

 

그 외에도 early_stopping_rounds 를 사용해서 눈에 띄지 않게 Loss가 감소하지 않은 경우에는 학습을 진행하지 않도록 제어도 가능합니다.

학습 성능의 경우에는 kaggle의 수차례 우승한 사례를 봤을 때, 충분히 우수하다고 판단됩니다.


 

 

단점 : Tree Based Learning, 복잡한 하이퍼 파라미터

 

모든 학습 알고리즘이 그렇듯, 장점과 단점이 있기 때문에 데이터의 분포나 상황에 알맞게 사용해야 합니다.

 

1. Tree Based Learning 를 학습할 때 학습 데이터에 예민하게 반응합니다.

학습 데이터에서 1~10 사이의 범주를 가진 라벨로 학습을 진행한 모델이 있다고 합시다.

이 모델은 데이터의 예측을 1 ~ 10 사이의 값으로 예측을 하고자 하고 10 초과, 1 미만으로 반환을 하기 어렵습니다.

 

2. 적절하게 튜닝을 하지 않은 모델은 Overfit이 쉽게 발생하는 문제 때문에 반드시 진행해야하는 절차입니다.

그런데 XGBoost는 튜닝을 할 때 손봐야할 파라미터가 너무 많습니다.

(당장 xgboost 공식 홈페이지에 가서 내용을 봐도, 파라미터가의 수가 너무 많습니다.)


소스코드

https://www.kaggle.com/ssooni/xgboost-lgbm-optuna

소스코드에는 XGBoost 외에도 LightGBM, Optuna, Stacking 앙상블을 사용한 내용도 있습니다.


,

Andrew Ng 교수님의 Machine Learning 강좌(http://www.coursera.org)

모두를 위한 머신러닝 강좌(http://hunkim.github.io/ml/)를 참고하여 포스팅하였습니다.


1. 선형 회귀

대표하는 직선!!  

왼쪽 그림과 같이 데이터가 분포하여 있을 때 X=9일 때 Y 값을 예측을 하고자 한다. 

단순히 왼쪽 그림만으로 Y 값을 예측하기에는 근거가 부족하다. 

우리가 4지 선다형 문제를 찍는 데에도 근거가 있으면 (예를 들면 답이 유독 4가 없다는 등)

묘하게 설득력이 생긴다. 통계학자들은 이런 근거를 만들고자 오른쪽과 같이 직선을 그어보았다.

이 직선 주변으로 데이터를 나타나는 점들이 분포하여 마치 데이터를 대표하는 모델로 역할을 수행한다.

따라서 이제 X=9에서 Y 값을 예측하는 것은 이 직선에서 X=9를 대입하면 끝!! 근거도 있어서 맘도 편하다.

이와 같은 방법으로 데이터를 예측하는 모델을 선형 회귀라고 하고, 이 직선의 방정식을 가설 함수라 한다.



직선 그리는 것도 각양각색

위의 그림에서 직선의 모양, 즉 가설 함수에 따라서 X=9일 때 예측값 Y의 값이 달라짐을 알 수 있다.

따라서 대표하는 직선을 어떤 기준으로 그릴 거냐는 문제가 발생한다.  



위의 그림에서 d는 원래 데이터의 값 y1과 예측값 H(x1)의 거리를 의미한다.

H(X)의 함수식 Θ1, Θ0에 따라서 d값이 달라질 것이며 어떤 점에 대해서는 너무 멀고 

어떤 점에서는 너무 가깝지 않는, 즉 분산이 최소가 되는 값을 구하여야 한다.

이 때 d값의 분산을 Cost Function이라 하고 Cost Function 최소가 되는 Θ1, Θ0를 구하는 것이 목표이다.



산을 타고 내려갑니다.

위의 그래프는 Θ에 따른 cost(Θ)의 변화이다. 앞서 말했듯이 우리가 원하는 것은 

cost(Θ)을 최솟값으로 만드는 Θ값을 구하는 것이다.

이때 사용하는 알고리즘이 Gradient descent이다. 쉽게 말해서 산타고 내려가는 것!! 

Θ를 일정한 양만큼 계속 줄여가면서 바닥으로 내려가는 것인데 만약 바닥이라면 기울기가 0이 되므로

위의 박스친 편미분 부분이 0이 되어 더 이상 감소하지 않는다. 

그리고 위의 식에서 α을 Learning rate라고 한다. α의 값은 개발자가 직접 설정해야 한다.

만약 α값이 너무 크면 바닥까지 내려오지 않을 수도 있고, α값이 너무 작으면 반복하는 횟수가 증가한다.

따라서 α값을 변형하면서 적절한 값을 찾는 것이 중요하다.


2. Tensorflow 구현

소스 코드 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import tensorflow as tf
import matplotlib.pyplot as plt
 
# 학습 데이터
X_data = [3.3,4.4,5.5,6.71,6.93,4.168,9.779,6.182,7.59,2.1677.042,10.791,5.313,7.997,5.654,9.27,3.1]
Y_data = [1.7,2.76,2.09,3.19,1.694,1.573,3.366,2.596,2.53,1.2212.827,3.465,1.65,2.904,2.42,2.94,1.3]
 
numOfData = len(X_data)     # 데이터의 갯수
alpha = 0.001               # Learning Rate alpha
itr = 3000                  # 반복 횟수 1000회
 
theta1 = tf.Variable(tf.random_uniform([1], 0.03.0))      # theta1
theta0 = tf.Variable(tf.random_uniform([1], 0.03.0))      # theta0
 
# H(x) = theta1 * x + theta0
hypothesis = tf.add(tf.mul(theta1, X_data), theta0)
 
# cost() = 1/2m * sum(pow(H(x) - y))
cost_function = tf.reduce_sum(tf.pow(hypothesis - Y_data, 2)) / (2 * numOfData)
 
# Gradient Descent 알고리즘
optimizer = tf.train.GradientDescentOptimizer(alpha).minimize(cost_function)
 
# 변수 초기화
init = tf.global_variables_initializer()
 
# Tensorflow session 시작
with tf.Session() as sess:
    sess.run(init)
 
    # 3000회 반복 수행
    for i in range(itr):
        sess.run(optimizer)
        if i % 20 == 0:
            print(i, sess.run(cost_function), sess.run(theta1), sess.run(theta0))
 
    # 데이터 시각화
    plt.plot(X_data, Y_data, 'ro', label='Training Data')
    plt.plot(X_data, sess.run(theta1) * X_data + sess.run(theta0), label='Linear Regression Result')
    plt.legend()
    plt.show()
 
 
cs

결 과


 

,