하이퍼파라미터 튜닝

 

1. 장점

- 다른  튜닝방법들이 존재하지만 상대적으로 빠르다고 할 수 있고

- 파라미터별 중요도를 직관적으로 확인할 수 있는 시각화까지 제공하여 용이하다

- 적용이 직관적이고 어렵지 않다는 장점 또한 뺴먹을수없다..

 

 

1. 모듈 임포트

import optuna
from optuna import Trial, visualization
from optuna.samplers import TPESampler

 

2. 목적값 정의

def lgbm_params_fold_start(lgb_params, X, y):
    
    skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=722)
    skf.split(X, X['Gender'])

    pred_list = []
    mae_list = []

    for fold,(train_index, val_index) in enumerate(skf.split(X,  X['Gender'])):

        print(f'***********{fold+1}th fold start***********')
        x_train, x_val, y_train, y_val = X.loc[train_index], X.loc[val_index], y.loc[train_index], y.loc[val_index]

        lgb = lightgbm.LGBMRegressor(**lgb_params, categorical_feature=[0])

        lgb.fit(x_train, y_train,
                eval_set=(x_val,y_val),
                eval_metric=NMAE, verbose=False, early_stopping_rounds=100)

        pred = lgb.predict(x_val)
        result = NMAE(pred,y_val)[1]

        mae_list.append(result)
        
    return np.mean(mae_list)

 

먼저 최적화될 모델을 정의한다. 나는 5폴드의 lgbm을 정의했고 주목해야할 점은  lgb_params를 받아 학습을 실시하고 최적화할 해를 리턴값으로 리턴하는다는점이다. 폴드를 적용하지 않는다면 objective에 바로 모델을 넣어도 무방하다.

 

def objectiveLGB(trial: Trial, X, y):
    param = {
        'boosting_type' : 'gbdt',
        "n_estimators" : 10000,
#         'fold_size':trial.suggest_int('fold_size', 4, 16),
        'max_depth':trial.suggest_int('max_depth', 4, 16),
        'random_state': 722,
        'reg_alpha': trial.suggest_loguniform('reg_alpha', 1e-8, 10.0),
        'reg_lambda': trial.suggest_loguniform('reg_lambda', 1e-8, 10.0),
        'num_leaves': trial.suggest_int('num_leaves', 8, 32),
        'colsample_bytree': trial.suggest_uniform('colsample_bytree', 0.5, 1.0),
        'subsample': trial.suggest_uniform('subsample', 0.8, 1.0),
        'subsample_freq': trial.suggest_int('subsample_freq', 1, 8),
        'min_child_samples': trial.suggest_int('min_child_samples', 16, 64),
        'learning_rate': 0.025
    }
    score = lgbm_params_fold_start(param, X, y)

    return score

이후 파라미터의 범위를 지정하는 objective함수를 정의한다. 

딕셔너리 형태로 정의하며 각 파라미터의 특성에 맞게 아래의 것으 선택하면되겠다.

 

- suggest_int : 범위 내의 정수형 값

ex) 'max_depth':trial.suggest_int('max_depth', 4, 16) 

 

- suggest_int : 범위 내의 실수형 값

ex) 'max_depth':trial.suggest_float('max_depth', 4, 16) 

 

* 위 두 방법은 log=True 메소드를 통해 로그값도 가능

 

- suggest_categorical : list 내의 데이터 선택

ex)  'colsample_bytree': trial.suggest_categorical('colsample_bytree', [0.5,0.6,0.7])

 

- suggest_uniform : 범위내의 균등분포를 값으로 선택

ex) 'colsample_bytree': trial.suggest_uniform('colsample_bytree', 0.5, 1.0)

 

- suggest_discrete_uniform : 범위내의 이산균등분포를 값으로 선택

ex) 'colsample_bytree': trial.suggest_uniform('colsample_bytree', 0.5, 1.0, 0.1)

 

- suggest_loguniform : 범위 내의 로그함수 선상의 값을 선택

ex) 'reg_lambda': trial.suggest_loguniform('reg_lambda', 1e-8, 10.0)

 

def objective(trial):
    x, y = ...
 
    classifier_name = trial.suggest_categorical("classifier", ["SVC", "RandomForest"])
    if classifier_name == "SVC":
        svc_c = trial.suggest_float("svc_c", 1e-10, 1e10, log=True)
        classifier_obj = sklearn.svm.SVC(...")
    else:
        rf_max_depth = trial.suggest_int("rf_max_depth", 2, 32, log=True)
        classifier_obj = sklearn.ensemble.RandomForestClassifier(...)
 
    accuracy = ...
    return accuracy

위 와같은 방법으로 모델 선택도 가능

 

 

3. 실행

 

study = optuna.create_study(direction='minimize',sampler=TPESampler(seed=42))
study.optimize(lambda trial : objectiveLGB(trial, X, y), n_trials=100)
print('Best trial: score {},\nparams {}'.format(study.best_trial.value,study.best_trial.params))

study 라는 객체를 생성하여 실행한다. 

 

- direction 은 목적한 objective 함수를 최소화할 것인지 최소화할것인지 입력한다 minimize, maximize

- sampler는 어떻게 값을 찾을 것인지 결정한다. 

https://optuna.readthedocs.io/en/stable/reference/samplers.html

 

객체의 optimize 메소드를 활용해 튜닝을 시작한다. 

- n_trials 는 시도횟수를 의미한다.

 

완료되면 study best_trial.value 메소드를 이용하여 목적함수의 값

best_trial.params 메소드를 이용해 파라미터들의 값을 받을 수 있다.

 

 

4. 시각화

 

optuna.visualization.plot_param_importances(study)

각 파라미터의 중요도를 나타내는 그래프

 

optuna.visualization.plot_optimization_history(study)

 

최적화 과정을 보여주는 그래프

'ML' 카테고리의 다른 글

[ML] 교차검증, cross-validation  (0) 2022.04.11
[ML] 인공신경망 학습  (0) 2022.02.17
[ ML ] 인공신경망 기본  (0) 2022.02.16
[ML] cycling encoding  (0) 2022.02.15
[ML] XGBoost - Classification  (0) 2022.01.18

 

교차 검증의 필요성

 

val

만약 위와 같이 train과 val set을 고정하고 학습한다면 학습과정에서 valset을 기준으로 학습 및 파라미터 튜닝이 진행 되기 때문에 val set에 과적합되는 경우가 생기게된다. 이를 해결하고자하는 것이 바로 교차검증이다.

 

장점

- 특정 val set에 과적합되는 것을 방지할 수 있다.

- 최대한 모든 데이터를 활용가능하다.

 

단점

- 학습의 속도가 k배로 늘어난다.

 

 

 

1. KFold 

데이터를 k 등분하고 각각 k-1개의 데이터를 trainset으로 나머지 하나의 데이터를 valset으로 활용하는 방법이이다.

 

from sklearn.model_selection import StratifiedKFold, KFold
from sklearn.metrics import mean_absolute_error

kf = KFold(n_splits=5, shuffle=True, random_state=722)

pred_list = []
mae_list = []

for fold,(train_index, val_index) in enumerate(kf.split(X)):

    print(f'***********{fold+1}th fold start***********')
    x_train, x_val, y_train, y_val = X.loc[train_index], X.loc[val_index], y.loc[train_index], y.loc[val_index]
    
    lgb = lightgbm.LGBMRegressor(boosting_type='gbdt',
        n_estimators=1000, random_state=722, learning_rate=0.05, categorical_feature=[0])

    lgb.fit(x_train, y_train,
            eval_set=(x_val,y_val),
            eval_metric='mae', verbose=False, early_stopping_rounds=100)

    pred = lgb.predict(x_val)
    result = mean_absolute_error(pred,y_val)
    
    mae_list.append(result)
    print(f'mae : {result:.4f}', end='\n\n')
    
print(f'mean mae {np.mean(mae_list):.4f}')
***********1th fold start***********
mae : 1.6950

***********2th fold start***********
mae : 1.6058

***********3th fold start***********
mae : 1.5267

***********4th fold start***********
mae : 1.5838

***********5th fold start***********
mae : 1.5302

mean mae 1.5883

kf = KFold(n_splits=5, shuffle=True, random_state=722)

- n_splits : k

- shuffle=True (섞을까?)

위와 같이 Kfold 객체를 생성하고 

for fold,(train_index, val_index) in enumerate(kf.split(X)):

split(x) 메소드로 각 인덱스를 받게 된다

 

이후 위의 코드처럼 학습을 진행하면된다.

 

2. StratifiedKFold

kfold를 하더라도 어느 fold의 트레인셋에 특정  class의 값이 편중되어있다면 해당클래스에 과적합될 것이다. 이를 방지하기 위하여 StratifiedKFold를 사용한다.

 

데이터를 k등분 한다는 점은 kfold와 같지만 StratifiedKFold는 범주형변수의 비율에 맞게 fold들을 반환한다.

 

예측하려는 변수가 범주형이라면 타겟을 fold를 나누는데에 활용하면 될 것이고

예측하려는 변수가 연속형이라면 타겟의 차이가 크게 나타나는 범주형변수나 구간화를 진행하여 활용하면 된다.

skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=722)

for fold,(train_index, val_index) in enumerate(kf.split(X)):

    print(f'***********{fold+1}th fold start***********')
    x_train, x_val, y_train, y_val = X.loc[train_index], X.loc[val_index], y.loc[train_index], y.loc[val_index]

'ML' 카테고리의 다른 글

[ML] 파라미터 튜닝 optuna - lgbm  (0) 2022.04.12
[ML] 인공신경망 학습  (0) 2022.02.17
[ ML ] 인공신경망 기본  (0) 2022.02.16
[ML] cycling encoding  (0) 2022.02.15
[ML] XGBoost - Classification  (0) 2022.01.18

https://www.youtube.com/watch?v=IHZwWFHWa-w&list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi&index=2&t=325s 

 

기계학습은 근본적으로 특정한 함수의 최솟값을 찾는 일로 요약될 수 있습니다.

 

개념상 각 뉴런은 이전 층의 모든 뉴런과 연결되어있고. 

가중치(Weight)는 연결의 세기라고 할 수 있고

편향(Bias) 뉴런이 활동적인지 비활동적인지를 나타내는 지표라고 할 수 있습니다.

 

학습을 위한 가장 첫번째 단계는 모든 가중치와 편향을 완전히 무작위로 설정하는 것 입니다.

이 신경망이 끔찍하게 작동할 것이라는건 아주 당연합니다.

 

그래서 우리가 할 일은 cost(비용)함수를 정의하는 것입니다.

 

코스트함수는 컴퓨터가 얼마나 틀렸는지를 알려주는 값이라고 생각하면 됩니다.

 

잘못된 출력값과 웒라는 출력차의 제곱을 모두 더하는 것입니다.

 

이제 수만가지의 트레인데이터셋에 대한 코스트를 검토하고 평균값을 계산합니다

 

여기서  기본적으로 신경망이 함수임을 기억해야합니다.

 

만약 분류를 잘했다면, 모델의 성능이 좋다면 코스트함수의 값이 작을 것이고

성능이 좋지않다면 코스트함수의 출력값이 클 것입니다.

모델의 목표는 성능을 좋게 하는 것이기 때문에 다시말하면 코스트함수의 값을 줄이는 것입니다.

 

 

이런 1차함수가 있다면 이 출력값을 최소화하는 입력값을 어떻게 찾을 수 있을까요

미적분을 배운사람이라면 정확하게 출력값을 최솟값으로하는 입력값을 알아낼 수 있을 것입니다.

하지만 항수가 많아진다면 항상 출력값을 최솟값으로하는 입력값을 알아 낼 순 없습니다.

 

저희가 풀어야하는 문제인 13002개의 인풋밸류가 있다면 알아내기가 더 어려워지겠죠.

 

이차원의 즉 두개의 입력변수가 있다고 가정하고

 

어떤 방향으로 입력변수들이 이동할때 손실함수가 작아지는지의 방향과 그 정도를 알아내야합니다.

 

 

이런식으로 반복적으로 그래디언트의 음의 방향으로 함수의 입력값을 이동하는 방식을

 

경사하강법(gradient desecent)이라고 합니다.

 

그래디언트를 계산하는 방법은 역전파 알고리즘으로 이루어지는데 역전파는 추후 기술합니다

 

 

 

그래디언트의 부호는 입력벡터의 값이 커져야할지 작아져야할지를 알려줍니다.

하지만 더 중요한 것은 이 값들의 상대적인 크기입니다.

 

어떤 값을 조정하는것이 다른 가중치를 조정하는 것보다 손실함수에 더 큰 영향을 미칠 수 있습니다.

 

딥러닝의 핵심은 손실함수를 최소화하는 골자기를 찾아가면서 그 방향과 정도를 미분으로 파악하는것

 

딥러닝의 놀라운점은 어떤 패턴을 찾아야하는지 알려주지도 않았는데 찾는다는것

5를 판단은 가능하지만 5를 그릴줄은 모른다는 점입니다.

 

'ML' 카테고리의 다른 글

[ML] 파라미터 튜닝 optuna - lgbm  (0) 2022.04.12
[ML] 교차검증, cross-validation  (0) 2022.04.11
[ ML ] 인공신경망 기본  (0) 2022.02.16
[ML] cycling encoding  (0) 2022.02.15
[ML] XGBoost - Classification  (0) 2022.01.18

본 게시글은 아래 영상을 기반으로 만들어졌다.

https://www.youtube.com/watch?v=aircAruvnKk 

 

 

 

딥러닝은 기존 인공신경망(Artificial Neural Network)의 한 종류이다. 

인공신경망은 사람 두뇌의 신경세포를 모방하여 수학적으로 모델링한 것으로 

데이터를 학습시는 머신러닝의 한 분야야다.

 

머신러닝의 한 범주이지만 타 머신러닝은 정형데이터를 다루는 반면, 딥러닝은 이미지, 영상, 텍스트 같은 비정형 데이터에 좋은 성능을 보이고있다.

 

 

이미지 출처 : Databricks, 인공신경망의 기본구조

 

인공신경망의 뇌의 어떤 점을 본딴 것일지 알아보자

 

뉴런은 0에서 1사이의 정보를 담는 다는 것만 알고 있으면된다.

이 숫자가 뉴런의 연결정도를 설명하는 수이다.

 

예를 들어 한 사람이 숫자를 보고 어떤 숫자인지 대답해야한다고 하자

28*28 픽셀

위의 이미지를 보면 대부분의 사람들은 숫자 9 라고 답할 것이다.

저 것을 어두운것은 0에 가깝게 밝은 것은 1에 가깝게 표현한다면 위와 같은 형태가 나올 것이다. 저 숫자들을 활성화 정도라고 표현한다.

 

우리가 숫자를 인식할 떄는 각 부분을 합친다

9의 경우에는 원부분과 ㅣ직선부분을 합치어

8의 경우에는 원부분 두개를 합친 모양

4의 경우 긴 수직선하나와 짧은 수직선 하나 짧은 수평선 하나를 합쳐 이루어진다.

 

이런 사람의 인식을 

 

 

은닉층에서 각각의 부분으로 인식하기를 기대한다.

 

분류 또는 예측을 할 때의 특징점을 은닉층에서 추출해내고 최종 결과에 활용하는것이다. 

 

이런 인식의 과정을 음성에서나 텍스트에서나 이미지에서나 기대하는 것이다.

 

저런 특징을 어떻게 뽑아낼까

 

이미지의 외곽선을 파악한다고 할때

모든 활성치를 가져와 어떠한 가중치와 곱하는 과정을 거친다. 곱하고 더한 이후의 값이

1에 가까우면 선부분 0에 가까우면 배경이라고 인식하게 하는 것이다.

시그모이드 함수

하지만 저런 가중합이 무조건 0과1사이라고 기대할 수 없다.

ㄸㅏ라서 어떠한 값을 0과1사이로 만들어 주는 시그모이드 함수에 가중합(추가로 편향을 더한다.)을 넣어 다음 뉴런에 들어갈 값을 정한다.

 

ㅇㅇ

이렇게 모든 가중치와 편향을 카운트하면 

13002의 서로다른 값을 계산하여야한다.

 

'ML' 카테고리의 다른 글

[ML] 교차검증, cross-validation  (0) 2022.04.11
[ML] 인공신경망 학습  (0) 2022.02.17
[ML] cycling encoding  (0) 2022.02.15
[ML] XGBoost - Classification  (0) 2022.01.18
[ML] XGBoost - Regression  (0) 2022.01.04

머신러닝에서 시간 같이 순환하는 숫자를 인코딩하는 방법이다.

 

시간을 예를 들어 설명하면 

 

00시와 23시는 숫자 적으로 본다면 23의 차이를 가진다 하지만 실제의 개념으로 본다면 1시간의 차이가 나는 것이다,

 

이를 해결하려고 보통의 머신러닝을 할떄는 시간을 범주형변수라고 전재하고 원핫 인코딩이나 카테고리컬형으로 처리하곤한다. 

 

하지만 이의 경우 시간의 거리를 무시하는 결과를 가지고 오게된다.

 

범주형 변수로 볼경우 23시와 0시의 차이와  12시와 0시의 차이를 같은 것으로 보게 된다.

 

이때 사용하는 인코딩 방법이 cycling encoding이다.

 

 

 

import numpy as np
time_list = list(range(0,24))
sin_list = list(map(lambda x : round(np.sin(2 * np.pi* x/24),4) ,time_list))
cos_list = list(map(lambda x : round(np.cos(2 * np.pi* x/24),4) ,time_list))

for i in time_list:
    print(f'{i}시의 좌표는 ({sin_list[i]},{cos_list[i]}) 입니다.')
    
    
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.scatter(sin_list, cos_list)

for i, txt in enumerate(time_list):
    ax.annotate(txt, (sin_list[i], cos_list[i]))
0시의 좌표는 (0.0,1.0) 입니다.
1시의 좌표는 (0.2588,0.9659) 입니다.
2시의 좌표는 (0.5,0.866) 입니다.
3시의 좌표는 (0.7071,0.7071) 입니다.
4시의 좌표는 (0.866,0.5) 입니다.
5시의 좌표는 (0.9659,0.2588) 입니다.
6시의 좌표는 (1.0,0.0) 입니다.
7시의 좌표는 (0.9659,-0.2588) 입니다.
8시의 좌표는 (0.866,-0.5) 입니다.
9시의 좌표는 (0.7071,-0.7071) 입니다.
10시의 좌표는 (0.5,-0.866) 입니다.
11시의 좌표는 (0.2588,-0.9659) 입니다.
12시의 좌표는 (0.0,-1.0) 입니다.
13시의 좌표는 (-0.2588,-0.9659) 입니다.
14시의 좌표는 (-0.5,-0.866) 입니다.
15시의 좌표는 (-0.7071,-0.7071) 입니다.
16시의 좌표는 (-0.866,-0.5) 입니다.
17시의 좌표는 (-0.9659,-0.2588) 입니다.
18시의 좌표는 (-1.0,-0.0) 입니다.
19시의 좌표는 (-0.9659,0.2588) 입니다.
20시의 좌표는 (-0.866,0.5) 입니다.
21시의 좌표는 (-0.7071,0.7071) 입니다.
22시의 좌표는 (-0.5,0.866) 입니다.
23시의 좌표는 (-0.2588,0.9659) 입니다.

이런식으로 하나의 변수였던 시간변수를 두가지의 변수로 쪼개어 순환하는 특성을 만드는 것이다.

 

시계바늘이나 풍향의 모습이라고 이해한다면 이해하기 쉬울 것이다.

 

나는 이런 특성과 다르게 트리기반 모델에 적용했을 때에도 스코어의 상승을 겪었다 하지만 수리적으로는 옳지 않다 

 

단 두가지의 변수를 만들기 때문에 분기시에 한가지의 변수를 이용하는 트리기반모델에는 적합치 않고 두변수의 관계를 한 번에 고려할 수 있는 신경망 모델에 적합한 인코딩 방법일 것이다.

 

 

'ML' 카테고리의 다른 글

[ML] 인공신경망 학습  (0) 2022.02.17
[ ML ] 인공신경망 기본  (0) 2022.02.16
[ML] XGBoost - Classification  (0) 2022.01.18
[ML] XGBoost - Regression  (0) 2022.01.04
[ML] Gradient Boost - Classification  (0) 2022.01.03

https://www.youtube.com/watch?v=8b1JEDvenQU&t=114s 

 

회귀의 방법보다 겉보기에는 복잡해 보이지만 이전 GB 분류와 XGB의 회귀를 결합한 방법이라서 큰 어려움은 없었다.

 

regression 의 경우와 마찬가지로 첫 예측은 0.5로 시작한다.

또한 잔차를 기반으로 트리를 생상하여 similarity score(앞으로 SM)을 계산한다.

분류문제에서는 아래의 식을 사용한ㄷ자

 

 

 

 

먼저 첫 분기점을 15로 두고  좌측노드의 sm을 계산하면 

위와 같은 결과를 얻게된다 (lambda = 0으로 가정) 같은 방법으로 우측노드를 계산하면 1이 나오고 

 

해당 분기점의 gain은 1.33 으로 얻어진다.

15가 아닌 다른 기준점으로도 계산을 실시하고 가장 gain이 큰 15를 첫 분기점으로 선택한다.

 

하위노드에도 같은 방법을 반복한다.

위와 같은경우에는 gain이 더 높은 dosage < 5 를 선택할 것이다

 

이제 여기서 cover라는 개념이 등장한다.

 

sm을 계산하는 식에서

빨간박스가 감싸고 있는 부분을  cover라고 하는데 cover가 기준 값을 넘지 못하면 가지치기를 한다고 이해하면 편하다

 

위의 예의 경우 cover가 1을 넘지 못하기때문에 가지치기되게된다.

 

regression과 동일하게 lambda 에 따라서 gamma를 넘지 못하는 노드 또한 가지치기된다.

 

이렇게 트리가 완성이되면

 

output을 꼐산한다.

위와 같은 식으로 결과값을 계산하는데 이는 GB의 결과값에 lambda가 추가된 형태이다.

 

모든 리프노드에 결과를 계산한면 위와같고

 

GB와 같은 방법으로 새로운 예측값을 계산한다.

 

가장 좌측노드의 예측확률은 위와 같게된다.

나온 확률의 잔차를 바탕으로 새로운트리를 만들기를 반복한다.

 

 

 

정리하면 similarity score를 계산한ㄷ,

 

1. 초기예측값으 0.5로 시작하고 오차를 계산한다

2. similarity score(lambda가 추가되어 좀더 규제된)를 계산하여 각 분기점의 gain을 계산하여 gain값이 높은 분기점을 선택하여 트리를만든다.

3. gamma값보다 gain이 크지않다면 가지치기를 진행한다.

4. 가지치기가 완료된 트리의 예측값을 계산한 후(lambda 반영) learning rate를 반영하여 예측값을 업데이트한다.

 예측값은 이전예측과 새로운예측 모두 로짓변환을 하여계산

5. 예측값을 바탕으로 다시 1~4의 과정을 중단규칙이 만족될때까지 반복한다.

'ML' 카테고리의 다른 글

[ ML ] 인공신경망 기본  (0) 2022.02.16
[ML] cycling encoding  (0) 2022.02.15
[ML] XGBoost - Regression  (0) 2022.01.04
[ML] Gradient Boost - Classification  (0) 2022.01.03
[ML] Gradient Boost - regression  (0) 2021.12.30

https://www.youtube.com/watch?v=OtD8wVaFm6E&t=404s 

 

XGBoost는 Extreme Gradient Boosting의 약자이다.

기존 GBㅇ에 추가로 Regularization 텀을 사용하여 과적합을 방지한다.

 

XGBoost 이름에 드러나 있듯 boosting 모델중 하나이다

 

 

 

XGB의 첫 예측값은  모델이 회귀든 분류모형이든  0.5를 사용한다.그리고 GB와는 달리 다른 방법으로 트리를 생성한다.

 

similarity score (앞으로 sim) 를 이용하는 방법이다.

similarity score 은 간단하게 말하면 최종 노드들이 얼마나 유사성을 띄는지로 해석할 수 있겠다.

유사성이 작다면 분류를 잘하지 못한것이고 유사성이 크면 분류를 잘한 것이라고 생각할 수 있다.

 

 

먼저 첫 예측값 0.5에 대해 잔차를 계산하여 sim값을 구한다. 이 때 먼저 트리를 생성하는 규칙에 대한 이해를 위해 

람다는 0이라고 가정하고 설명을 이어나가겠다.

 

각 노드들의 sim을 구하면 해당 분기점의 gain을 얻을 수 있다. 이제 

15가 아닌 다른 경계값에서 계산을하면

dosage < 22.5 -> gain = 4

dosage < 30 -> gain = 56.33

 

이다 이때 gain이 가장높은 dosage < 15를 첫분기점으로 한다.

Regression tree를 만들 때 한 연속형 feature의 threshold를 설정하기 위해 모든 경계값의 rmse를 계산했던 것과 같다.

 

하위노드에도 반복하면

 

위와 같은 트리를 얻을 수 있다.

이제 과적합을 방지하기위해서는 가지치기를 해야한다. 

 

가지치기를 위해서는 gain의 경계값을 설정해야한다. gain 이 특정값(앞으로 gamma)보다 작다면 즉
gain - gamma < 0 일 경우 해당 분기점은 없어진다.

 

위의 경우 gamma가 130 일시에는 트리가 그대로 유지되지만

gamma가 150 일시에는 모든 분기점이 삭제가되고 최초의 예측값만 남게된다.

 

이제 미루어두었던 Regularization term 람다에 대해서 설명을 이어나가보자

lamda를 1이라고 가정하고 위의 계산을 이어나가면

 

위와 같은 sim값을 얻게된다 sim값이 많이 떨어진 것을 확인할 수 있다..

 

즉 sim이 낮아지기에 가지치기를 하게될 확률이 아주 높아진다고할 수 있다.

다시 말하면 과적합이 방지가된다.

 

만약 gamma가 0이라도 gain값이 음수라면 당연히 가지치기를 진행한다.

 

이제 트리를 만들었으니 output value를 계산한다.

output value에도 아까 마주했던 lambda가 있는 것을 확인할 수 있다.

람다가 0이라면 평균갑이 출력될것이고 그것이 아니라면

더 작은값이(더 조심스러운) 값이 출력될 것이다.\

 

그 이후과정은 다른 GB모델과 같이

 

learnig rate를 반영하여 값을 업데이트한다. 

 

정리하면

1. 초기예측값으 0.5로 시작하고 오차를 계산한다

2. similarity score(lambda가 추가되어 좀더 규제된)를 계산하여 각 분기점의 gain을 계산하여 gain값이 높은 분기점을 선택하여 트리를만든다.

3. gamma값보다 gain이 크지않다면 가지치기를 진행한다.

4. 가지치기가 완료된 트리의 예측값을 계산한 후(lambda 반영) learning rate를 반영하여 예측값을 업데이트한다.

5. 예측값을 바탕으로 다시 1~4의 과정을 중단규칙이 만족될때까지 반복한다.

 

'ML' 카테고리의 다른 글

[ML] cycling encoding  (0) 2022.02.15
[ML] XGBoost - Classification  (0) 2022.01.18
[ML] Gradient Boost - Classification  (0) 2022.01.03
[ML] Gradient Boost - regression  (0) 2021.12.30
[ML] Adaboost  (0) 2021.12.29

https://www.youtube.com/watch?v=jxuNLH5dXCs&t=130s 

 

1. odds
GB를 분류에 사용할때는 중요한 개념이 사용된다. 로지스틱회귀분석에 사용되는 odds라는 개념이다.

 

odds = 성공확률 / 실패확률 = (성공건수/전체건수) / (실패건수/전체건수) = 성공건수/ 실패건수

 

이진분류에서 실패확률 = 1 - 성공확룔이기때문에 

p를 성공확률이라고 할때

odds  = p/(1-p) 라고 할 수 있다.

 

간단히 생각하면 오즈가 클수록 성공확률이크다는 것을 의미한다.

위 오즈에 로그를 취한 값을 로그오즈 (logit로짓)이라고 하는데

자세한 오즈에 대한 설명은 로지스틱회귀분석에 대한 포스팅을 진행할 때 살펴보자

 

 

 

 

2. GB

누군가가 트롤 2를 좋아할 로짓은 log(4/2) = 0.7 이다. 

이것이 GB의 첫 예측값이 된다.

 

로지스틱회귀분석과 같이 GB의 분류문제에서는 로짓을 이용하는 방법은

확률로 변환하는 방법이다.

 

 

위와 같이 확률을 계산하면 확률이 나오게된다.

(위값은 설명에 용이하게하기위해 반올림을 한 것임정확히 계산한다면 0.6667이 나올것)

확률이 0.5보다 크게 나왔으니 1이라고 분류할 것이다.

여기서 0과 1로 구분하는 구분점을 threshold라한다. 이것은 바귈수있다. roc aoc

 

 

이제 나온 확률을 바탕으로 실제값과의 잔차를 구하여 얼마나 잘 예측했는지를 평가한다.

 

이제 잔차를 예측하는 트리를 이전과 같이 만든다.

이전의 GB처럼 당연히 리프의 개수는 제한되어있다.

 

이제 회귀문제보다는 좀 더 복잡한 문제가 발생한다.

0.7이라는 값은 로짓의 추정값이고 리프노드의 값은 확률값이기 때문에 리프노드의 값을 로짓으로 변환할 필요가 있다.

이때 가장 보편적으로 사용되는 변환방법은

 

 

위와 같다.

 

좌측에서 두번째 노드의 예측 로짓은

이 되는 것이다.  이 과정을 모든 리프노드에 반복하면 

 

로짓을 예측하는 트리가 완성이 되는것이다.

 

이제 예측값을 업데트한다.

learning rate를 0.8이라고 했을때 가장 우측노드의 경우

 

로짓의 새로운 예측값은 

1.8이고 이를 확률로 변환하면 

0.9가 된다. 이렇게 모든 row에 확률을 구하고 잔차를 구하면

위와 같은 결과를 얻게된다.

나온 확률의 잔차를 바탕으로 새로운트리를 만들기를 반복한다.

 

정리하면

 

1. 모든 row에대한 로짓을 계산.

2. 잔차를 예측하는 트리 생성. 이때 리프노드의 값은 로짓으로 변환해 계산.

3. learning rate를 가중하여 새로운 로짓값을 업데이트를 하고 그로부터 새로운 확률을 계산하여 잔차를 업데이트

 

2~3을 중단조건이 만족될 떄가지 반복한다,

 

 

예측을 할때에는 최종 트리에서 확인할 수 있는 로짓값을 확률로 변환하여 최종예측

 

 

'ML' 카테고리의 다른 글

[ML] XGBoost - Classification  (0) 2022.01.18
[ML] XGBoost - Regression  (0) 2022.01.04
[ML] Gradient Boost - regression  (0) 2021.12.30
[ML] Adaboost  (0) 2021.12.29
[ML] Randomforest  (0) 2021.12.29

adaboost 는 stump의 오차를 이용하여 더 나은 stump를 만드는 과정이었다.

그에 반해 gradient boost(앞으로 GB)는 리프노드로 부터 첫예측을 실시하고 그에 대한 

잔차를 바탕으로 새로운 트리를 업데이트해나가는 과정이다. 그 잔차를 계산함에 있어서 미분이 사용되어 gradient(기울기) boost라 불린다.

loss function의 미분값이 다음학습의 정답이 된다.

 

 

 

트리모델의 특성상 트리의 깊이가 깊어지게되면 과적합의 위험이 큰데 이를 방지하기위하여 크기가 제한된 트리를 이용한다. 물론 ada boost의 stump보다는 크기가 큰 트리이다.

 

가장 보편적인 방법으로 GB를 설명하겠다..

위와 같은 데이터가 있다고 가정할 때 가장 편하게 데이터를 예측할 방법은

데이터의 평균값을 이용하는 것일 것이다.

 

GB는 평균값을 첫 예측값으로 이용하고 예측값과 관측값의 오차를 바탕으로 새로운 트리를 만들어 낸다.

 

각 잔차를 계산하면 위와 같은 결과가 얻어지는데

이제 산출된 잔차를 바탕으로 트리를 만든다.

 

 

잔차를 예측하는 decision tree를 만들게 된다,

 

 

잔차를 바탕으로 위의 row를 예측하면 

 

88이라는 정확한 예측결과를 얻을 수 있다.

 

하지만 저 값은 과적합된 결과일 수 있다. 실제로 샘플데이터가 굉장히 작아서 과적합이 발생한 것이다.

 

그렇기에 GB에서는 learning rate라는 개념을 사용한다.

 

잔차에 learning rate를 곱해 원예측값에 더한 값을 새로운 예측값으로 활용하게된다.

 

 

 

이제 만들어지 두번째 잔차로 두번쨰 트리를 만들어 위의 과정을 반복한다.

 

GB 미리 설정한 중단조건을 충족하기 전까지 위의 과정을 반복한다. 과적합을 피하면서, 점점 원 관측값에 가까워지는 것이다.

 

정리하면

 

1. 첫 예측값은 target의 평균

2. 예측값을 바탕으로 오차를 예측하는 트리생성

3. 예측값 + 트리로 예측한 오차 * leanig rate로 예측값을 업데이트

 

2~3을 중단조건이 만족될 떄가지 반복

 

 

 

 

 

 

 

 

 

 

 

 

 

'ML' 카테고리의 다른 글

[ML] XGBoost - Regression  (0) 2022.01.04
[ML] Gradient Boost - Classification  (0) 2022.01.03
[ML] Adaboost  (0) 2021.12.29
[ML] Randomforest  (0) 2021.12.29
[ML] Regression Tree  (0) 2021.12.28

 

 

 

1. 부스팅이란?

 

여러모델을 결합하는 것을 앙상블이라고 하는데 앙상블은 배깅과 부스팅 두가지로 나뉜다.

간단히말하면

배깅은 여러데이터를 샘플링하여 각자 독립적인 모델을 만들고 각각 같은 가중의 투표를 하는데에반해

부스팅은 한모델을 만들고 그 모델의 오차를 바탕으로 다음모델을 만든다. 그후에 그 각각의 모델이 설명을 얼마나잘하는지에 가중치를 두어 그 가중치에 맞춘 최종리턴을 선정한다.

 

2. Adaboost

에이다부스트는 부스팅 모델의 가장 기본적인 형태이다.

에이다 부스트의 가장 큰 특징이라고 한다면 분기점이 한번을 이후로 나눠지지 않는다는 것이다. 즉 바로 리프노드가 나오는 구조이다. 이런 구조를 tree라고 하지않고 stump라고 한다.

 

1) 이런 약한 학습모델인 stump들을 결합시킨 것이 adaboost이다.

2) 각각 stump들은 각자의 amount of say(설명력)을 가진다 

3) 각각의 stump들은 이전의 stump의 오차에따라 변화한다.

 

위의 세가지 개념을 가지고 adaboost는 이루어진다.

 

2-1. sample weight

 

adaboost부터는 sample weight라는 개념이 처음으로 등장한다. 최초의 sample weight는 1/전체 자료의 수 이지만

만들어진 stump가 얼마나 잘예측했는지에따라서 weight가 업데이트된다.

간단히 짚고 넘어가자면 현재 stump가 예측을 잘못한 데이터일수록 sample weigh값이 올라가고 다음 모델을 위한 학습 데이터에 포함될 확률이 올라간다.

 

stump를 만드는 것부터 차근차근히 과정을 살펴보자

 

먼저 스텀프를 만들때에 decision tree의 첫 과정처럼 지니계수를 비교하여 질문을 선택한다.

위의 예에서는 가장 지니계수가 낮은 weight > 176 이 선택된다.

 

이후 모델에서 잘 분류한 녀석과 그러지 못한녀석을 식별하여 sample weght를 업데트한다.

이제 이모델의 total error과 amount of sat를 계산한다.

 

Total Error = 분류에 실패한 녀석들의 sample weght의 합

 

total error가 높아지면 amount of say는 낮아지고

total error가 낮아지면 amount of say는 높아지고

total error가 1/2 이면 즉 분류확률이 반반이면 amount of say는 0 이된다.

 

이제 이 값으로 대략적으로 이 stump가 데이터를 얼마나 예측하는지를 수치적으로 확인할 수 이있다.

 

위 예의 total error  =1/8 이고 amount of say = 0.97이다.

 

 

이제 amount of say를 바탕으로 sample weigt를 업데이터해야한다.

잘못분류한 데이터의 경우

위와 같이 업데이트가 되고 

잘 분류한경우

 

이렇게 계산이되고

각각 새로은 가중치를 반영하면

 

이런식의 표형태가 나온다. 그 가중치를 합이 1이되게 조정을하면 normweight가 나온다.

반올림하느라 weight의 합이 1이 아니다

이제 저 norm weight를 바탕으로 다음 stump의 생성에 사용될 데이터를 샘플링한다..

그 방법은 다음과 같다

0~1 사이의 난수를 생성한다.

난수 0.72은 0.7 보다 크고 0.77보다 작으므로 다섯번째 데이터를 넣는다.

난수 0.42은 0.21 보다 크고 0.7보다 작으므로 네번째 데이터를 넣는다.

난수 0.83은 0.77 보다 크고 0.84보다 작으므로 여섯번째 데이터를 넣는다.

난수 0.72은 0.7 보다 크고 0.77보다 작으므로 다섯번째 데이터를 넣는다.

 

이런식으로 원데이터의 갯수만큼 반복하여 새로운 데이터를 만든다. 이제 이데이터를 바탕으로 다음  stump를 만드는것이다. 

새로운 데이터를 보면 같은 데이터가 4번 반복된다. 첫 stump에서 예측에 실패한데이터에 높은 가중치를 줬기때문에

여러면 샘플링 된 것이다. 이렇게 새로운데이터는 이전 stump에서 실패한 데이터를 더 많이 학습하게 되어있다.

그 이후 새로운데이터에 대해서는 sample weight를 초기화한다.

 

 이런 과정을 여러번 반복하여 여러 stump를 만든다.

 

 

이제 여러 stump를 가지고 최종결과를 찾아야한다. 

모두 동일한 투표권을 가지는 배깅과는 달리

adaboosting은 각각 모델의 amount of say의 합을 비교하여 최종결과를 산출한다.

위 예의 경우 한 row를 넣었을때

yes라고 대답한 stump들의 amout of say의합이 no라고 대답한 stump들의 amout of say의 합보다 크므로

해당 row에 대하여 yes라는 결론을 내린다.

 

 

 

스텀프를 만들고 그를 바탕으로 새로운 스텀프를 만들고 반복해 만들어진 여러 스텀프들의 설명력의 합을 비교하여 결론을 내린다

'ML' 카테고리의 다른 글

[ML] Gradient Boost - Classification  (0) 2022.01.03
[ML] Gradient Boost - regression  (0) 2021.12.30
[ML] Randomforest  (0) 2021.12.29
[ML] Regression Tree  (0) 2021.12.28
[ML] Decision tree  (0) 2021.12.28

+ Recent posts