fizzbuzz by xgboost
XGBoostのFizzBuzzです
勾配ブースティングでもFizzBuzzできるという例を示します
DeepLearningならばFizzBuzzの3の倍数と5の倍数と15の倍数の時に、特定の動作をするというルールを獲得することは容易なのですが、他の機械学習アルゴリズムはどうでしょうか
XGBoostはその決定木の性質と、勾配ブースティングの学習アルゴリズムを解析的に説明した論文の内容を見ると、特定のルールを獲得することは難しくないんじゃないかと思いました[1]
ただ、FizzBuzzを数値として扱ってしまうと、かなり厄介で、連続する値が大きい小さいなどで判別するのは容易ではありません
DeepLearning時と同じように、Character Levelで入力を扱います
数字を文字表現として皆して、各桁の数字を一つの特徴量として扱います
クラスは”3の倍数の時のFizz”,”5の倍数の時のBuzz”,”15の倍数の時のFizzBuzz”,”その他”の時の4つのクラスの分類問題にしました
softmaxではなくて、softprobを用いました
ドキュメントを読むと、各クラスの所属する確率として表現されるようです(クラスの数ぶん、sigmoidが配置されていると、同じ?)
0〜99999までの数字の各FizzBuzzを利用します
この時、2割をランダムでテストデータに、8割を学習データに分割します
このようにしました、もっと最適な設定があるかもしれないので、教えていただけると幸いです
etaが大きいのは、極めてroundが多いので、これ以上小さくするとまともな時間に学習が完了しません
booster = gbtree
objective = multi:softprob
num_class = 4
eta = 1.0
gamma = 1.0
min_child_weight = 1
max_depth = 100
subsample = 0.8
num_round = 100000
save_period = 1000
colsample_bytree = 0.9
data = "svm.fmt.train"
eval[test] = "svm.fmt.test"
#eval_train = 1
test:data = "svm.fmt.test"
githubにコードが置いてあります
$ python3 createDataset.py --step1 # データセットの作成
$ python3 createDataset.py --step2 # 前処理
$ python3 createDataset.py --step3 # libsvmフォーマットを作成
(xgboost.binはubuntu linux 16.04でコンパイルしたバイナリです。環境に合わせて適宜バイナリを用意してください)
(学習には、16コアのRyzen 1700Xで2時間程度かかります)
$ ./xgboost.bin fizzbuzz.train.conf
(必要に応じて、使用するモデルを書き換えてください)
$ ./xgboost.bin fizzbuzz.predict.conf
$ python3 predCheck.py
50000roundでテストデータで以下の精度が出ます
acc 0.9492
出力はこのようになります
12518 predict class = 3 real class = 3
42645 predict class = 2 real class = 0
15296 predict class = 3 real class = 3
47712 predict class = 3 real class = 1
1073 predict class = 3 real class = 3
66924 predict class = 1 real class = 1
82852 predict class = 3 real class = 3
26043 predict class = 1 real class = 1
96556 predict class = 3 real class = 3
81672 predict class = 1 real class = 1
44018 predict class = 3 real class = 3
16622 predict class = 3 real class = 3
79924 predict class = 3 real class = 3
15290 predict class = 2 real class = 2
25276 predict class = 3 real class = 3
class 2は15の倍数なのですが、これの獲得が難しいようです
一応、違う機械学習との比較ともやるべきでしょう
L2-regularized L2-loss support vector classificationで動作する、liblinearで比較しました
$ ./train -s 1 svm.fmt.train
....*.*
optimization finished, #iter = 52
Objective value = -56679.234880
nSV = 64068
.....*
optimization finished, #iter = 51
Objective value = -56678.857821
nSV = 65083
....*.
optimization finished, #iter = 50
Objective value = -14306.576984
nSV = 17032
.....*
optimization finished, #iter = 51
Objective value = -14305.608585
nSV = 16957
$ ./predict svm.fmt.test svm.fmt.train.model output
Accuracy = 66.2298% (13240/19991)
精度が66%しか出ていません
やはり、XGBoostの精度で判別をすることはできないようです
DeepLearningでは精度100%を達成できましたが、XGBoostでは95%程度の精度です
完全なルールの獲得は怪しいですが、それでもかなりいいところまで行っているようです
また、目的関数をうまく設計すれば、もっといけるでしょう(勾配ブースティングのマルチラベル分類、どうやるんだろう)