LoginSignup
3
2

More than 5 years have passed since last update.

Optuna×XGBoostでred_wine_quality

Last updated at Posted at 2019-02-22

はじめに

XGBoostをクラス分けではなく回帰に使ってみる.(と言いつつも、結果は10クラス分類)
ということで、いろんな要素から赤ワインのQualityを当てるモデルを作る.
結論から言うと、あまり精度は出なかった.

実行環境とライブラリ

前回の記事を参照

実装

  1. 適当なパラメータでやる(max_depth, learning_rate, round_num)
  2. 1のパラメータをoptunaにかける
  3. パラメータを沢山にする

XGBoostにある2つの回帰アルゴリズム
* 線形回帰
* ロジスティック回帰
どっちも試した.
また,データ属性は全部使ってみる.

前処理

preprocess
def preprocess(df):
    df[target_column] = df[target_column] /10
    return df

ロジスティック回帰を用いるために,Quality[0,10]を[0,1]の少数として扱う.
最大値で割ろうかと思ったが,無限小数とかになった時に,精度が全く出なさそうなので10で割った.
元データがすでに全て数値なので、数値変換はしない.
全属性を使うのでdropもしない.

XGBoostによる学習

train
def train(df,max_depth,learning_rate,num_round,how_objective):
    train_x = df.drop(target_column,axis=1)
    train_y = df[target_column]
    dtrain = xgb.DMatrix(train_x,label=train_y)
    param = { 'max_depth':max_depth,'learning_rate':learning_rate,'objective':how_objective,'silent':1}
    bst = xgb.train(param,dtrain,num_round)
    return bst

target_columnは目的変数

optunaの目的関数の定義

objective
def objective(df, df_test, y, how_objective, trial):
    #目的関数
    max_depth = trial.suggest_int('max_depth',1,30)
    learning_rate = trial.suggest_uniform('learning_rate',0.0,1.0)
    round_num = trial.suggest_int('round_num',1,30)
    bst = train(df,max_depth,learning_rate,round_num,how_objective)
    answer = predict(bst,df_test).round().astype(int)
    score = accuracy_score(answer,y.astype(int))
    return 1.0 - score

max_depth, learning_rate, round_numについてチューニングを行う。

main関数

main
def main():
    global target_column
    df_original = pd.read_csv("/Users/pc1013/Desktop/first/XGBoost_optuna/df/winequality-red.csv")
    df = preprocess(df_original)
    (df_train, df_test) = train_test_split(df, test_size = 0.1, random_state = 666)
    y = df_test[target_column]*10
    df_test = df_test.drop(target_column,axis=1)

    how_objective = 'reg:logistic' #or 'reg:linear'

    '''
    学習と結果出力
    必要があればoptunaの前処理とチューニング
    '''

実行結果

パラメータを適当にやる

#ハイパーパラメータ
    max_depth = 6
    learning_rate = 0.1
    round_num = 10

上から、linearとlogistic
wine_quality_linear.png
wine_quality_logistic.png

3つのパラメータを自動チューニング

上からlinearとlogistic

wine_quality_1_linear.png
wine_quality_1_log.png

完璧なオーバーフィッティング

沢山のパラメータを自動チューニング

上からlinearとlogistic

wine_quality_2_linear.png
wine_quality_2_log.png

改良

データ前処理の変更

  • 寄与率の低かった、citric acid, free sulfur dioxide, sulphatesをデータセットから削除する

optunaの変更

  • 試行回数(n_trial)を200回 パラメータの範囲を
  • max_depth ≤ 30
  • round_num ≤ 30
  • learning_rate ≤ 1.0
  • gamma ≤ 10.0
  • min_childe_weigh ≤ 10.0
  • alpha ≤ 10.0 とする
def preprocess(df):
    df = df.drop(['citric acid','free sulfur dioxide','fixed acidity','alcohol'],axis=1)
    df[target_column] = df[target_column] /10
    return df
#ハイパーパラメータの範囲(objective関数内)
    max_depth = trial.suggest_int('max_depth',1,25)
    learning_rate = trial.suggest_uniform('learning_rate',0.0,1.0)
    round_num = trial.suggest_int('round_num',1,30)
    gamma = trial.suggest_uniform('gamma',0.0,10.0)
    colsample_bytree = trial.suggest_uniform('colsample_bytree',0.0,1.0)
    min_childe_weigh = trial.suggest_uniform('min_childe_weigh',0.0,10.0)
    alpha = trial.suggest_uniform('alpha',0.0,10.0)

実行結果 #2

上からlinearとlogistic
wine_quality_imprline.png
wine_quality_2_log.png

過学習がマシになった...? (なってない)

まとめ

精度が出ない。
自動化と言っても、過学習を防ぐために、ハイパーパラメータの範囲の調整が必要だった。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2