はじめに
XGBoostをクラス分けではなく回帰に使ってみる.(と言いつつも、結果は10クラス分類)
ということで、いろんな要素から赤ワインのQualityを当てるモデルを作る.
結論から言うと、あまり精度は出なかった.
実行環境とライブラリ
実装
- 適当なパラメータでやる(max_depth, learning_rate, round_num)
- 1のパラメータをoptunaにかける
- パラメータを沢山にする
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
3つのパラメータを自動チューニング
上からlinearとlogistic
完璧なオーバーフィッティング
沢山のパラメータを自動チューニング
上からlinearとlogistic
改良
データ前処理の変更
- 寄与率の低かった、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
過学習がマシになった...? (なってない)
まとめ
精度が出ない。
自動化と言っても、過学習を防ぐために、ハイパーパラメータの範囲の調整が必要だった。