目的
交差検証について調べたりコード化してみる
そもそもの発端としては
前回の訓練データだと90ぐらいのスコアになったのをアップロードしてみたらちょこっとしかUPしてなかったということである。
以下のようなろくでもない検証にしかしてなかったのでダメだろうとは思っていたが
ここまで差が出るとはちょっとびっくりであった。
evaluation_score = round(model.score(features , target) * 100, 2)
なので、調べてみることにした。
[過剰適合]
https://ja.wikipedia.org/wiki/%E9%81%8E%E5%89%B0%E9%81%A9%E5%90%88
[交差検証]
https://ja.wikipedia.org/wiki/%E4%BA%A4%E5%B7%AE%E6%A4%9C%E8%A8%BC
ググってみた。
「モデルの説明変数は必要以上に増やせば増やすほど学習データのシグナルだけでなくノイズにまでフィットしてしまう」
訓練データに最適化しすぎると、訓練データ内のノイズについても何かしらのモデルから生成されたものなのではないかという推論モデルを構築してしまうということなわけだ。
これは仕事の世界でも割とありそうな話。
また、これは割と嫌な話ですが「交差検証したからと言って汎化性能が確保できるとは限らない」ケースもあるということ。特に学習データと(テストデータではない本当の)新規の未知データとで性質が全く違うようなケースでは、いかな汎化性能の高いモデルでも太刀打ちできません。時々Kaggleでその手のデータセットが出てきて物議を醸すことがありますが、実務でも同様のことは少なくないです。
そして実装へ
交差検証のロジックを調べて実装してみるかなーと思って捜索してたらびっくりした。
https://qiita.com/yhyhyhjp/items/d4b796f7658b7e5be3b6
scikit-learnのモジュールの中にあるらしい。
・・・みなが扱うのだから、それもそうか。
ちなみに上記に記載してあるとおりに実装してみると何やらワーニングが出た。
C:\Program Files\Anaconda3\lib\site-packages\sklearn\cross_validation.py:44: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20. "This module will be removed in 0.20.", DeprecationWarning)
と思ったら、その上でcross_validationをimportしていたからっぽい。
from sklearn import cross_validation # ←ここでワーニング
from sklearn.model_selection import cross_val_score
scores = cross_val_score(model, features, target)
# pprint.pprint(scores)
# 各分割におけるスコア
print('Cross-Validation scores: {}'.format(scores))
# スコアの平均値
# import numpy as np
evaluation_score = np.mean(scores)
print('Average score: {}'.format(evaluation_score))
cross_validationは使えなくなるのでmodel_selectionにしないといけないらしいのだが、そもそもまだ未使用なのでコメントアウトしておく
※参考:https://qiita.com/kasajei/items/e23929627d51aa1b09fe
ドキュメントも見てみる
cvの数を変えるとどうなるのか?
li = [i for i in range(4, 10)]
li.append(100)
for n in li:
print('Average score {}: {}'.format(n, np.mean(cross_val_score(model, features, target, cv=n))))
↓
Average score: 0.7833894500561166
Average score 4: 0.7991231041259068
Average score 5: 0.8047747932733926
Average score 6: 0.8036383699135378
Average score 7: 0.8060033232453085
Average score 8: 0.8071141555516557
Average score 9: 0.8035914702581368
Average score 100 : 0.8036111111111112
こんな感じだ。
100にしたからといってそこまで精度が上がるということでもなさそう。
というか、何をもって「精度が上がった」と言っているのかも自分ではよくわからない。
なので、とりあえず5ぐらいとして実施してみることにする。
この状態で各モデルに対して改めて検証してみる。
model_name score
0 DecisionTree 0.804775
6 Random Forest 0.804775
1 LogisticRegression 0.790168
4 Gaussian Naive Bayes 0.789031
3 k近傍法(KNN) 0.700442
2 Support Vector Machines 0.697160
5 Perceptron 0.627463
DecisionTreeがRandom Forestを逆転するという結果に。
また、Random Forestもsocreはよいが、前回ほどアホみたいな数値にはなっていない。
実際はこれよりも下がると考えると常識的な数値が出る検証となったと言えるかもしれない。
ただ、この検証スコアを信じるとDecisionTreeの方が高い結果になるはずなのだが、
前回アップロードした結果だとRandom Forestの方が若干高い。難しいな。
ハイパーパラメータのチューニング
交差検証を調べていたら以下の記事に遭遇
https://qiita.com/tomov3/items/039d4271ed30490edf7b
これの後半にモデルに対するパラメータのチューニングの仕方が載っていた。
※というか、本来は体系立てて学習していくことな気もしてきたがとりあえず気にしない。
なので、TODOとしてはモデルに対するパラメータチューニングもそのうち試してみるやることにする。