交差検証(CrossValidation)

同じ出処から取ってきたデータを全て訓練データとして使わずに、
訓練データとテストデータに分割して、訓練データで作ったモデルに対するテストデータの精度を返す、
みたいなことをやるらしい。交差検証(CrossValidation)という名前が付いている、


sklearn.model_selection.cross_val_score(
   estimator, X, y=None, groups=None,
   scoring=None, cv=’warn’, n_jobs=None,
   verbose=0, fit_params=None,
   pre_dispatch=‘2*n_jobs’, error_score=’raise-deprecating’)

estimatorとして、例えば決定木分類であればDecisionTreeClassifierのインスタンスを渡す。
Xは説明変数、yは目的変数。交差検証自体のアルゴリズムを選択できてcvに渡す値で制御できる。

学習済みのモデルを渡してスコアが戻るのではなく、
単なるモデルのインスタンスと学習前のデータを別々に渡している作りなのを見ると、
モデル毎のスコアを並べてみたくなる..。そういう使い方するのか?
“スコア”と言ってるこの値は具体的には何の値なのか..?

K-分割交差検証(K-fold cross-validation)の場合cvは以下のようになる。
cvを省略するとK=3が使われる。使ったデータは例のあやめ。


clf = DecisionTreeClassifier(max_depth = 3)
# integer, to specify the number of folds in a (Stratified)KFold,
score1 = cross_val_score(estimator = clf, X = iris.data, y = iris.target, cv = 10)
# None, to use the default 3-fold cross validation,
score2 = cross_val_score(estimator = clf, X = iris.data, y = iris.target)

決定木の深さを交差検証で求める(失敗)

suumoから引いてきた家賃~占有面積,築年数,階数,バストイレ別データについて、
目的変数を家賃、説明変数を占有面積、築年数、階数、バストイレ別として決定木を作ってみた。
決定木の深さは交差検証で求める、と書かれているので以下のようにしてみた。


import sys
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import tree
from sklearn.model_selection import train_test_split
from sklearn.model_selection import cross_val_score

path = "./fuchu.csv"
train = pd.read_csv(filepath_or_buffer=path)
train = train.drop_duplicates()

feature_name = ["area","age","bt_separated"]
feature_name2 = ["area"]
train_x = train[feature_name2].values
train_y = train["value"].values
sort_idx = train_x.flatten().argsort()

max_depth_list = [1,3,5,7,9,11,13,15,17]
for max_depth in max_depth_list:
        regressor = tree.DecisionTreeRegressor(max_depth = max_depth)
        regressor.fit(train_x,train_y)
        score = cross_val_score(estimator=regressor,X=train_x,y=train_y)
        print([max_depth,score.mean()])

結果、おかしい…。マイナスってなんだ。


[1, -0.020456885057637583]
[3, 0.012376893473610817]
[5, -0.014519973352621932]
[7, -0.03332646095737912]
[9, -0.06862181989491711]
[11, -0.09590667631145984]
[13, -0.1345799052512994]
[15, -0.1529266053016934]
[17, -0.17054978124438266]

説明変数を占有面積だけに絞って散布図書いて、その上に回帰結果をプロットすると、
異常値の0に引っ張られて乱れてた…。以下は深さ=17の時。むぅ.
真ん中の塊の中を左下から右上に向かってギザギザに進んで欲しいのだが、
物凄い引っ張られよう。異常値が原因というよりは、引っ張られ過ぎなんだな。