NGBoost를 사용하여 분포를 예측해 보았습니다.

GBDT로 예측 분포를 낼 수 있으면 화제의 NGBoost를 시험해 보았으므로, 비망록이 주로 투고합니다. 실제로 움직이고 싶은 분은 여기 를 참고해 주세요.

소감


  • 모델 튜닝을 거의 하지 않은 상태이며, 이번 작은 데이터 세트에서는 정밀도는 거의 같다.
  • 분포를 산출할 수 있는 것은 사용지점이 있을지도 모르겠네요.

  • 가져오기



    나중에 NGBoost와 LightGBM을 조금 비교하므로 lightgbm도 가져옵니다.
    # ngboost
    from ngboost.ngboost import NGBoost
    from ngboost.learners import default_tree_learner
    from ngboost.scores import MLE
    from ngboost.distns import Normal, LogNormal
    
    # lightgbm
    import lightgbm as lgb
    
    # skleran
    from sklearn.datasets import load_boston
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import mean_squared_error
    

    데이터 준비



    회귀 문제의 보스톤 데이터 세트를 sklearn에서 가져옵니다. 수백 줄의 가벼운 데이터입니다. 홀드 아웃으로 확인합니다.
    X, y = load_boston(True)
    rd.seed(71)
    X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2)
    X_train.shape, X_valid.shapae
    

    [output]
    ((404, 13), (102, 13))
    

    NGBoost 학습



    인스턴스 만들어 fit은 같습니다. 예측 분포를 검색하려면 pred_dist를 사용합니다.
    %%time
    rd.seed(71)
    ngb = NGBoost(Base=default_tree_learner, Dist=Normal, #Normal, LogNormal
                  Score=MLE(), natural_gradient=True, verbose=False, )
    ngb.fit(X_train, y_train, X_val=X_valid, Y_val=y_valid)
    
    y_preds = ngb.predict(X_valid)
    y_dists = ngb.pred_dist(X_valid)
    
    
    # test Mean Squared Error
    test_MSE = mean_squared_error(y_preds, y_valid)
    print('ngb Test MSE', test_MSE)
    
    #test Negative Log Likelihood
    test_NLL = -y_dists.logpdf(y_valid.flatten()).mean()
    print('ngb Test NLL', test_NLL)
    

    [output]
    ngb Test MSE 9.533862361491169
    ngb Test NLL 3.8760352
    CPU times: user 8.35 s, sys: 1.82 s, total: 10.2 s
    Wall time: 6.27 s
    

    비교를 위한 LightGBM 학습



    64 core CPU로 돈을 돌렸기 때문에 한순간에 학습이 끝납니다.
    %%time
    lgb_train = lgb.Dataset(X_train, y_train)
    lgb_valid = lgb.Dataset(X_valid, y_valid, reference=lgb_train)
    model = lgb.train({'objective': 'regression', 
               'metric': "mse",
               'learning_rate': 0.01,
               'seed': 71},
                lgb_train, 
                num_boost_round=99999,
                valid_sets=[lgb_valid], 
                early_stopping_rounds=100, 
                verbose_eval=500)
    
    y_pred_lgb = model.predict(data=X_valid)
    

    [output]
    Training until validation scores don't improve for 100 rounds.
    [500]   valid_0's l2: 10.8615
    [1000]  valid_0's l2: 10.0345
    [1500]  valid_0's l2: 9.66004
    Early stopping, best iteration is:
    [1651]  valid_0's l2: 9.57796
    CPU times: user 3min 51s, sys: 223 ms, total: 3min 51s
    Wall time: 3.62 s
    

    정확도 비교



    모델 튜닝은 제대로 하지 않습니다. 그래서 어느 것이 성능이 좋은지는 모르겠지만, 겨우 사용한 느낌으로는 이 정도의 데이터라면 손색 없네요.


    모델
    유효 MSE


    NGBoost
    9.53386

    LightGBM
    9.57796


    NGBoost 분포 시각화



    NGBoost의 분포를 시각화했습니다. 여기가 NGBoost의 키모라고 생각합니다!
    각 그리드의 1 매스가 X_valid의 1 레코드 마다 대응하는 예측 결과가 됩니다. X_valid가 102행이므로 그래프도 102개 출력됩니다.
    모델의 예측 결과는 정규 분포를 채용하고 있기 때문에 평균을 점 추정하고 있는 것을 알 수 있습니다.



    표시 관계에서 처음 네 줄만 표시합니다. 모두 보고 싶은 분은 여기 를 봐 주세요.

    위의 그래프를 그리는 코드는 이쪽.
    offset = np.ptp(y_preds)*0.1
    y_range = np.linspace(min(y_valid)-offset, max(y_valid)+offset, 200).reshape((-1, 1))
    dist_values = y_dists.pdf(y_range).transpose()
    
    plt.figure(figsize=(25, 120))
    for idx in tqdm(np.arange(X_valid.shape[0])):
    
        plt.subplot(35, 3, idx+1)
        plt.plot(y_range, dist_values[idx])
    
        plt.vlines(y_preds[idx], 0, max(dist_values[idx]), "r", label="ngb pred")
        plt.vlines(y_pred_lgb[idx], 0, max(dist_values[idx]), "purple", label="lgb pred")
        plt.vlines(y_valid[idx], 0, max(dist_values[idx]), "pink", label="ground truth")
        plt.legend(loc="best")
        plt.title(f"idx: {idx}")
        plt.xlim(y_range[0], y_range[-1])
    plt.tight_layout()
    plt.show()
    

    결과 비교(산포도)



    NGBoost vs LightGBM



    대체로 할머니 예측치를 내고 있네요.


    Ground Truth와의 비교



    Ground Truth와 비교해 보면, 양쪽 모두 같은 경향의 출력 결과로 보이네요.




    contribution



    early stopping이 없거나, 학습의 순차 로그가 ON/OFF 밖에 없어, 100step마다 로그 출력할 수 없다든가, 상당히 여러가지 contribution 찬스가 있을 것 같아요, 여러분! w

    참고


  • 이번 실험의 Notebook:
    htps //w w. 꺄gぇ. 코 m / 켄 마츠 4 / ng 보오 st-g 뻬시 온 -
  • 공식 페이지:
    htps : // s단후 rdmlg 납 p. 기주 b. 이오/p로지ぇcts/응g보오 st/
  • Github 리포지토리:
    htps : // 기주 b. 코 m / s 탄후 rdml 왁스 p / ng g 보오 st
  • Github 저장소 : example (이번 전 자료)
    htps : // 기주 b. 이 m/s단후ぉrdmlg 엎드려서 p/응g보오 st/bぉb/마s테 r/에ぁmpぇs/에 m피리카 l/레그 떡. py
  • 좋은 웹페이지 즐겨찾기