俺人〜OREGIN〜俺、バカだから人工知能に代わりに頑張ってもらうまでのお話

俺って、おバカさんなので、とっても優秀な人工知能を作って代わりに頑張ってもらうことにしました。世界の端っこでおバカな俺が夢の達成に向けてチマチマ頑張る、そんな小さなお話です。現在はG検定、E資格に合格し、KaggleやProbSpaceのコンペに参画しながら、Pythonや機械学習、統計学、Dockerなどの勉強中です。学習したことをブログにアウトプットすることで、自分の身に着けていきたいと思います。まだまだ道半ばですが、お時間がありましたら見て行ってください。

エピソード3-13: AdaBoostに挑戦してみる。Acc66%→67.5%(KaggleでKickstarter Projectsに挑戦する。)

「Kaggle」のデータセットKickstarter Projects」に取り組んでいます。

今回は、一度NNモデルから離れて、木モデルのAdaBoostに挑戦します。

NNモデルの記事は、以下にありますので、ご参照ください。

oregin-ai.hatenablog.com

 

では、さっそく取り組んでまいります。

 1.まずは、Leakageになりそうなカラム、相関が強いカラムをドロップする。

# ラベルデータとして’state’を採用する。
train_label = df_train['state']

# Leakageになりそうなカラム、相関が強いカラムをドロップする
train_data = df_train.drop(['state','name','currency','deadline','goal','launched','pledged','backers','usd pledged','usd_pledged_real','period'], axis=1) 

 

2.標準化する。

# 標準化 
train_data = (train_data - train_data.mean()) / train_data.std()
train_data = train_data.astype('float32') 

平均との差分を、標準偏差で割って、値を標準化します。 

3.ホールドアウト法で、最終的に性能を見るためのテストデータを別にする。

テストデータは30%にします。

#ホールドアウト法に関する関数をインポートする。
from sklearn.model_selection import train_test_split
# 交差検証法に関する関数をインポートする。
from sklearn.model_selection import KFold
#目的変数'state'を正解としてyに格納
adB_y = adB_train_label.values
#カラムをドロップした説明変数を、Xに格納
adB_X = adB_train_data.values

# 全データのうち、30%をテストデータにする
test_size = 0.3

# ホールドアウト法を実行(テストデータはランダム選択)
#X_train : 学習用データの説明変数
#X_test : テスト用データの説明変数
#y_train : 学習用データの目的変数
#y_test : テスト用データの目的変数
adB_X_train, adB_X_test, adB_y_train, adB_y_test = train_test_split(adB_X, adB_y, test_size=test_size,shuffle=True, random_state=1234) 

print(adB_X_train.shape, adB_X_test.shape, adB_y_train.shape, adB_y_test.shape)

 (144879, 199) (62091, 199) (144879,) (62091,)

学習用のデータが144879個、テスト用のデータが62091個に分離できました。

4.max_depth(木の深さ)を変化させて、Accuracyが最大になる値を探す。

AdaBoostを使って、木の深さを変化させて、検証データのAccuracyが最大になる値を探索することにしました。
探索にあたっては、交差検証法(クロスバリデーション)を利用しました。
#木の深さ毎のAccuracy格納用データフレームを初期化
df_md_Acc = pd.DataFrame(index=[], columns=['max_depth','val_acc'])
#木の深さ毎に検証する。 for max_depth in np.arange(1,10,1): #クロスバリデーションの検証毎のAccuracy格納用データフレームを初期化 df_val_Acc = pd.DataFrame(index=[], columns=['val_acc']) #クロスバリデーションでの検証ステップを初期化 #クロスバリデーションで検証 for train_index, test_index in KFold(n_splits=2,shuffle=True,random_state=1234).split(adB_X_train, adB_y_train): adB_X_val_train, adB_X_val_test = adB_X[train_index], adB_X[test_index] adB_y_val_train, adB_y_val_test = adB_y[train_index], adB_y[test_index] clf = AdaBoostClassifier(DecisionTreeClassifier(max_depth=max_depth,min_samples_split=2,random_state=1234,criterion="gini"),n_estimators=10, random_state=1234) clf.fit(adB_X_val_train, adB_y_val_train) score = clf.score(adB_X_val_test, adB_y_val_test) print("max_depth=",max_depth) print("score=", score) val_se = pd.Series( [score], index=df_val_Acc.columns ) df_val_Acc = df_val_Acc.append(val_se, ignore_index = True,sort=False) md_df = pd.DataFrame(index=[],columns=['max_depth','val_acc']) md_df = md_df.append(df_val_Acc.mean(),ignore_index = True,sort=False) md_df['max_depth'] = max_depth df_md_Acc = df_md_Acc.append(md_df, ignore_index = True,sort=False)

以下の結果が得られました。

display(df_md_Acc)
display(df_md_Acc.max())
  max_depth val_acc
0 1 0.723286
1 2 0.758233
2 3 0.764852
3 4 0.765508
4 5 0.765784
5 6 0.763789
6 7 0.763658
7 8 0.761898
8 9 0.759385

val_acc 0.765784 dtype: float64

df_md_Acc[['val_acc']].plot()
plt.show()

f:id:kanriyou_h004:20190616170607p:plain

グラフ上の横軸とmax_depthの値が1ずれているのでわかりにくいですが、四番目(max_depth=5)のVal_Accが最大になっているので、5をmax_depthとして採用する。

5.訓練データをすべて投入し、テストデータでの精度を確認する。

AdaBoostに訓練データをすべて投入し、max_depth=5で学習させます。
clf = AdaBoostClassifier(DecisionTreeClassifier(max_depth=5,min_samples_split=2,random_state=1234,criterion="gini"),n_estimators=10, random_state=1234)
clf.fit(adB_X_train, adB_y_train)
print("score=", clf.score(adB_X_test, adB_y_test))
 
score= 0.6750253659950718
クロスバリデーション時から、精度が下がりましたが、なんとか精度が67.5%まで改善し、NNモデルより精度が向上しました。

 

6.木モデルでつかわれている説明変数を確認する。

AdaBoostのfeature_importance_を利用して、このモデルでつかわれている説明変数を確認します。
# 説明変数の重要度を出力する
# 棒グラフで出力する。 pd.DataFrame(clf.feature_importances_, index=adB_train_data.columns).plot.barh(figsize=(12,50)) plt.ylabel("Importance") plt.xlabel("Features") plt.show()

f:id:kanriyou_h004:20190616172104p:plain

LassoCVで選択した特徴量よりも大幅に少なくなっています。また、usd_goalも利用されていて、直感的な特徴量が採用されている気がします。

 

今回は、視点を変えて、木モデル(AdaBoost)を試したのですが、これまでより、少ない特徴量で効率的な分類モデルができたと思われます。でも、まだまだ、全く役に立たないレベルの精度なので、いったん初心に戻って、テキスト等を参考に、理論を学びなおしたいと思います。

 

 2019年3月9日(土)にG検定を受験し、見事合格できました!

受験の体験記や勉強法などを別のブログにまとめました。

これから受験される方がいらっしゃいましたらご参考まで。

g-kentei.hatenablog.com