Python
初心者
機械学習
crossvalidation
GridSearch

Pythonによるスクレイピング&機械学習のお勉強その4-7 - データの検証方法について

今回の目標

このシリーズでは教科書(文献1)に沿ってPythonによるスクレイピングと機械学習を学びます。今回は第4章「機械学習」から4-7「データの検証方法について」を学びます。
実際には、クロスバリデーションとグリッドサーチが解説されています。

このシリーズの学習では、原則教科書のサンプルプログラムを作成してゆきますが、著作権に配慮し、できるだけそのままではなく類題を作成して勉強してゆく方針です。

今回取り上げられている手法について

クロスバリデーション

Cross validationはデータを訓練データ、テストデータに分割して学習とテストを行うことによりモデルの妥当性を検証する方法です。クロスバリデーションの中にもいくつかの手法があるらしいのですが、今回はデータをk分割して、1つをテストデータ、残りを学習データとして、k通りの検証を行うk-fold cross validationが取り上げられています。

グリッドサーチ

グリッドサーチは複数のパラメータを総当たりで調べ、最適な組み合わせを調べる方法です。手動で行うこともありますが、scikit-learnの学習器については自動でグリッドサーチを行う仕組みが提供されています。

方法と結果

  • 準備

その0で作成した学習用docker環境でpythonの実行を行います。

$ docker run -t -i -v $HOME/src:$HOME/src -p 8080:8080 pylearn2 /bin/bash

教科書での学習事項の整理

今回、教科書ではアヤメの分類データを用いて、k-fold cross validation (k = 5)を自前のコードで行う課題(cross-iris.py)とscikit-learnで提供されている機能を使って行う課題(cross-iris2.py)が記載されています。
また、グリッドサーチについてはMNISTのSVM分類の学習器のパラメータをグリッドサーチする課題(grid-mnist.py)が記載されています。

今回は、この学習シリーズ4-4で作成した簡易ライブラリにcross validationとgrid searchを行う機能を付加して、類題としたいと思います。

なお、記事執筆時点(2018/6)では教科書に記載のscikit-learn内のcross_validationをimportするとdeprecation warningが出る状態で、将来的にcross_validationモジュールは削除されるとのことです。代わりにmodel_selectionモジュールをimportします。
教科書記載のcross_val_scoreとGridSearchCVについてはimport文だけ変えればそのまま使えそうです。

類題4-7-1 自作簡易ライブラリにcross validationとgrid searchを実装

いずれも簡易ライブラリのpylearn_classification.pyに記載します。

pylearn_classification.py
#(前略)
from sklearn.grid_search import GridSearchCV
#(中略)
class Classifier:
#(中略)
   #K-fold cross validationを行う
    #foldingにk分割のkを指定する。
    #dataを指定しなければself.traindataを使用する
    #dataを指定する場合はClassifyTaskData形式
    def cross_validation(self, folding, data=None):
        if data is None:
            data = self.traindata

        if self.classifier is None:
            self.classifier = self.algorithm.value()

        print(data.datasetname(), 'のデータのクロスバリデーションを行います(k=', folding, ')')

        validating_data = data.getdata()
        #normalizerの設定
        if self.normalizer is not None:
            validating_data = self.normalizer(validating_data)

        scores = model_selection.cross_val_score(self.classifier, validating_data, numpy.ravel(data.getlabel()), cv=folding)
        print('各正解率=', scores, ', 平均正解率=', scores.mean())

    #Grid searchを行う
    #paramにはGridSearchCVに与えるのと同様、辞書型または辞書型のリストを与える
    #グリッドサーチにはself.traindataを用いる
    def grid_search(self, param, testdata):
        data = self.traindata

        if self.classifier is None:
            self.classifier = self.algorithm.value()

        print('学習器', str(self.classifier), 'のパラメータグリッドサーチを行います。')
        cl_old = self.classifier
        self.classifier = GridSearchCV(self.classifier, param, n_jobs=-1, verbose=2)

        #グリッドサーチを行う
        self.train()
        print('ベストデータ: 学習器=', self.classifier.best_estimator_)
        #テストデータで確認
        self.classify(testdata)

        #もとの学習器に戻す
        self.classifier = cl_old
#(後略)

これで実装できました。

類題4-7-2 MNISTの学習データをcross validation

MNISTの学習データをk=10でcross validationしてみます。コードはMNISTの簡易ライブラリ対応版(その4-4で作成)のメインプログラム部分をちょっと改変するだけです。
cross validationには時間がかかるので、試してみるのは60000件ある学習データではなく、10000件のテストデータの方です。

mnist_crossvalidation.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pylearn as pl
import pylearn_classification as plc
import mnist_cclef_4_4 as mnc
import random
from os.path import join
from urllib.parse import urljoin

#####   MNIST の画像認識プログラムのための設定  #####

# MNIST画像データを保存するディレクトリ
MNISTPATH = './mnist_cclef_4_4'

#使用する学習アルゴリズム
#plc.AlgorithmのEnum内から選択します。
ALGORITHM = plc.Algorithm.SVC

#MNISTデータのベースURL 通常は変更の必要はありません。
MNISTBASEURL = 'http://yann.lecun.com/exdb/mnist/'

#MNISTデータのファイルリスト 通常は変更の必要はありません。
MNISTFILELIST = [
    'train-images-idx3-ubyte.gz',
    'train-labels-idx1-ubyte.gz',
    't10k-images-idx3-ubyte.gz',
    't10k-labels-idx1-ubyte.gz'
]

#######


### ここからメインプログラム

# データのダウンロードと保存
print('MNISTデータのダウンロードと保存を行います。')
for f in MNISTFILELIST:
    URL = urljoin(MNISTBASEURL, f)
    pl.dl_save(URL, MNISTPATH, 'binary')

# 学習用データセットの準備
train_labelpath = join(MNISTPATH, MNISTFILELIST[3])
train_imgpath = join(MNISTPATH, MNISTFILELIST[2])

traindata = mnc.MNISTdata(train_labelpath, train_imgpath)

# 学習用データセットの検証
validation = traindata.validate()

if validation is False:
    quit()

# 学習器の準備
cl = plc.Classifier(ALGORITHM, traindata)
cl.setNormalizer(traindata.getnormalizer())

# 学習用データセットのcross validationを行う
cl.cross_validation(3)

類題4-7-2 実行結果

MNISTデータのダウンロードと保存を行います。
train-images-idx3-ubyte.gz はすでに存在するためダウンロードしません
train-labels-idx1-ubyte.gz はすでに存在するためダウンロードしません
t10k-images-idx3-ubyte.gz はすでに存在するためダウンロードしません
t10k-labels-idx1-ubyte.gz はすでに存在するためダウンロードしません
アイテム数検証 OK;  10000 件のデータがあります。
MNISTデータの検証に成功しました。label= ./mnist_cclef_4_4/t10k-labels-idx1-ubyte.gz , image= ./mnist_cclef_4_4/t10k-images-idx3-ubyte.gz
MNIST のデータのクロスバリデーションを行います( k= 3 )
各正解率= [0.88615938 0.91479148 0.91859417] , 平均正解率= 0.9065150094814817

3つともそこそこ近い値が出ました。

類題4-7-3 クレアチニンクリアランスの分類タスクでgrid search

次はgrid searchの練習です。SVMによる分類で成績の悪かったクレアチニンクリアランスのタスクの成績向上を試してみます。学習器はSVMを使います。
例によって、その4-4で作ったコードをちょっとだけ改変して使います。

ccr_svm_gridsearch.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pylearn_classification as pcl

####config#####
#ccr.csvのパス
CCRCSV = './ccr.csv'

#学習に用いるアルゴリズム
ALGORITHM = pcl.Algorithm.SVM

#プロットするグラフの種類
PLOTTYPE = [ 'hist', 'line' ]

#この変数は通常変更不要
INDEX_TITLE = [ 'year', 'sex', 'height', 'weight', 'cr' ]
LABEL_TITLE = [ 'CKD grade' ]
#####


#CCrの分類データを保持するクラス
class CCrData(pcl.ConcreteClassifyTaskData):

    def __init__(self, ccrdatapath=None):
        parent = super(CCrData, self)
        parent.__init__('CCr Data')
        self.path = ccrdatapath
        if ccrdatapath is not None:
            dattup = CCrData.readTitledCSV(self.path, INDEX_TITLE, LABEL_TITLE)
            self.setdata(dattup[0])
            self.setlabel(dattup[1])

    @classmethod
    def create_skeleton(cls, datasetname):
        skeleton = cls()
        parent = super(CCrData, skeleton)
        parent.__init__(datasetname)
        return skeleton

class CCrNormalizer(pcl.Normalizer):

    def __call__(self, data):
        normalized = data.copy()
        shape = data.shape

        #性別を50倍する
        sliced = normalized.iloc[1]
        sliced *= 50
        normalized.iloc[1] = sliced

        #crを50倍する
        sliced = normalized.iloc[4]
        sliced *= 50
        normalized.iloc[4] = sliced
        return normalized


#グリッドサーチのパラメータ
#SVM用に記載
GSPARAM = [
    { 'C': [0.1, 1, 10, 100], 'kernel':['linear'] },
    { 'C': [0.1, 1, 10, 100], 'kernel':['rbf'], 'gamma':[0.0001, 0.001, 0.01] },
    { 'C': [0.1, 1, 10, 100], 'kernel':['poly'], 'degree':[1, 2, 3], 'gamma':[0.0001, 0.001] },
    { 'C': [0.1, 1, 10, 100], 'kernel':['sigmoid'], 'gamma':[0.0001, 0.001] }
]

### メインプログラム

#データの準備
#全体データの作成
wholedata = CCrData(CCRCSV)

#指標とラベルのタイトル名のセット
wholedata.setdatatitle(INDEX_TITLE)
wholedata.setlabeltitle(LABEL_TITLE)


traindata, testdata = wholedata.train_test_split()

#学習器の準備
cl = pcl.Classifier(ALGORITHM, traindata)
cl.setPlotType(PLOTTYPE)
cl.setNormalizer(CCrNormalizer())

#グリッドサーチを実行
cl.grid_search(GSPARAM, testdata)

類題4-7-3 実行結果

グリッドサーチには時間がかかるとのことなので、ccr.csvは2000件のみのデータで行います。
調子にのってたくさんパラメータを試そうとすると、本当に数時間では終わらないレベルになってしまいました。今回掲載しているパラメータの組は、私の環境では数分で終わります。

$ python ./ccr_svm_gridsearch.py
Algorithm.SVM
学習器 SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
  decision_function_shape='ovr', degree=3, gamma='auto', kernel='rbf',
  max_iter=-1, probability=False, random_state=None, shrinking=True,
  tol=0.001, verbose=False) のパラメータグリッドサーチを行います。
CCr Data_train から 1500 件の学習を実行します。
Fitting 3 folds for each of 48 candidates, totalling 144 fits
[CV] C=0.1, kernel=linear ............................................
[CV] C=0.1, kernel=linear ............................................
[CV] C=0.1, kernel=linear ............................................
[CV] C=1, kernel=linear ..............................................
[CV] C=1, kernel=linear ..............................................
[CV] C=1, kernel=linear ..............................................
[CV] C=10, kernel=linear .............................................
[CV] C=10, kernel=linear .............................................
[CV] C=10, kernel=linear .............................................
[CV] C=100, kernel=linear ............................................
[CV] C=100, kernel=linear ............................................
[CV] C=100, kernel=linear ............................................
[CV] ................................... C=0.1, kernel=linear -   0.7s
[CV] C=0.1, gamma=0.0001, kernel=rbf .................................
[CV] ................................... C=0.1, kernel=linear -   0.8s
[CV] C=0.1, gamma=0.0001, kernel=rbf .................................
[CV] ........................ C=0.1, gamma=0.0001, kernel=rbf -   0.2s
[CV] C=0.1, gamma=0.0001, kernel=rbf .................................
[CV] ................................... C=0.1, kernel=linear -   0.9s
[CV] ........................ C=0.1, gamma=0.0001, kernel=rbf -   0.2s
[CV] C=0.1, gamma=0.001, kernel=rbf ..................................
[CV] C=0.1, gamma=0.001, kernel=rbf ..................................
[CV] ........................ C=0.1, gamma=0.0001, kernel=rbf -   0.1s
[CV] C=0.1, gamma=0.001, kernel=rbf ..................................
[CV] ......................... C=0.1, gamma=0.001, kernel=rbf -   0.1s
[CV] C=0.1, gamma=0.01, kernel=rbf ...................................
[CV] ......................... C=0.1, gamma=0.001, kernel=rbf -   0.2s
[CV] C=0.1, gamma=0.01, kernel=rbf ...................................
[CV] ......................... C=0.1, gamma=0.001, kernel=rbf -   0.2s
[CV] C=0.1, gamma=0.01, kernel=rbf ...................................
[CV] .......................... C=0.1, gamma=0.01, kernel=rbf -   0.2s
[CV] C=1, gamma=0.0001, kernel=rbf ...................................
[CV] .......................... C=0.1, gamma=0.01, kernel=rbf -   0.2s
[CV] C=1, gamma=0.0001, kernel=rbf ...................................
[CV] .......................... C=0.1, gamma=0.01, kernel=rbf -   0.2s
[CV] C=1, gamma=0.0001, kernel=rbf ...................................
[CV] .......................... C=1, gamma=0.0001, kernel=rbf -   0.2s
[CV] C=1, gamma=0.001, kernel=rbf ....................................
[CV] .......................... C=1, gamma=0.0001, kernel=rbf -   0.2s
[CV] C=1, gamma=0.001, kernel=rbf ....................................
[CV] .......................... C=1, gamma=0.0001, kernel=rbf -   0.2s
[CV] C=1, gamma=0.001, kernel=rbf ....................................
[CV] ........................... C=1, gamma=0.001, kernel=rbf -   0.2s
[CV] C=1, gamma=0.01, kernel=rbf .....................................
[CV] ........................... C=1, gamma=0.001, kernel=rbf -   0.1s
[Parallel(n_jobs=-1)]: Done  17 tasks      | elapsed:    1.7s
[CV] C=1, gamma=0.01, kernel=rbf .....................................
[CV] ........................... C=1, gamma=0.001, kernel=rbf -   0.2s
[CV] C=1, gamma=0.01, kernel=rbf .....................................
[CV] ..................................... C=1, kernel=linear -   1.8s
[CV] C=10, gamma=0.0001, kernel=rbf ..................................
[CV] ............................ C=1, gamma=0.01, kernel=rbf -   0.2s
[CV] C=10, gamma=0.0001, kernel=rbf ..................................
[CV] ............................ C=1, gamma=0.01, kernel=rbf -   0.2s
[CV] ............................ C=1, gamma=0.01, kernel=rbf -   0.2s
[CV] C=10, gamma=0.0001, kernel=rbf ..................................
[CV] C=10, gamma=0.001, kernel=rbf ...................................
[CV] ......................... C=10, gamma=0.0001, kernel=rbf -   0.2s
[CV] C=10, gamma=0.001, kernel=rbf ...................................
[CV] ......................... C=10, gamma=0.0001, kernel=rbf -   0.2s
[CV] C=10, gamma=0.001, kernel=rbf ...................................
[CV] ......................... C=10, gamma=0.0001, kernel=rbf -   0.2s
[CV] C=10, gamma=0.01, kernel=rbf ....................................
[CV] .......................... C=10, gamma=0.001, kernel=rbf -   0.2s
[CV] C=10, gamma=0.01, kernel=rbf ....................................
[CV] .......................... C=10, gamma=0.001, kernel=rbf -   0.2s
[CV] C=10, gamma=0.01, kernel=rbf ....................................
[CV] .......................... C=10, gamma=0.001, kernel=rbf -   0.2s
[CV] C=100, gamma=0.0001, kernel=rbf .................................
[CV] ........................... C=10, gamma=0.01, kernel=rbf -   0.3s
[CV] C=100, gamma=0.0001, kernel=rbf .................................
[CV] ........................... C=10, gamma=0.01, kernel=rbf -   0.3s
[CV] C=100, gamma=0.0001, kernel=rbf .................................
[CV] ........................ C=100, gamma=0.0001, kernel=rbf -   0.3s
[CV] C=100, gamma=0.001, kernel=rbf ..................................
[CV] ........................ C=100, gamma=0.0001, kernel=rbf -   0.2s
[CV] ........................... C=10, gamma=0.01, kernel=rbf -   0.3s
[CV] C=100, gamma=0.001, kernel=rbf ..................................
[CV] C=100, gamma=0.001, kernel=rbf ..................................
[CV] ..................................... C=1, kernel=linear -   2.6s
[CV] C=100, gamma=0.01, kernel=rbf ...................................
[CV] ........................ C=100, gamma=0.0001, kernel=rbf -   0.4s
[CV] C=100, gamma=0.01, kernel=rbf ...................................
[CV] ..................................... C=1, kernel=linear -   2.9s
[CV] C=100, gamma=0.01, kernel=rbf ...................................
[CV] .......................... C=100, gamma=0.01, kernel=rbf -   0.3s
[CV] C=0.1, degree=1, gamma=0.0001, kernel=poly ......................
[CV] ......................... C=100, gamma=0.001, kernel=rbf -   0.5s
[CV] C=0.1, degree=1, gamma=0.0001, kernel=poly ......................
[CV] .......................... C=100, gamma=0.01, kernel=rbf -   0.3s
[CV] C=0.1, degree=1, gamma=0.0001, kernel=poly ......................
[CV] ............. C=0.1, degree=1, gamma=0.0001, kernel=poly -   0.1s
[CV] C=0.1, degree=1, gamma=0.001, kernel=poly .......................
[CV] ......................... C=100, gamma=0.001, kernel=rbf -   0.6s
[CV] ............. C=0.1, degree=1, gamma=0.0001, kernel=poly -   0.1s
[CV] C=0.1, degree=1, gamma=0.001, kernel=poly .......................
[CV] C=0.1, degree=1, gamma=0.001, kernel=poly .......................
[CV] ............. C=0.1, degree=1, gamma=0.0001, kernel=poly -   0.1s
[CV] C=0.1, degree=2, gamma=0.0001, kernel=poly ......................
[CV] ............. C=0.1, degree=2, gamma=0.0001, kernel=poly -   0.1s
[CV] C=0.1, degree=2, gamma=0.0001, kernel=poly ......................
[CV] .............. C=0.1, degree=1, gamma=0.001, kernel=poly -   0.1s
[CV] ......................... C=100, gamma=0.001, kernel=rbf -   0.7s
[CV] C=0.1, degree=2, gamma=0.0001, kernel=poly ......................
[CV] .......................... C=100, gamma=0.01, kernel=rbf -   0.3s
[CV] C=0.1, degree=2, gamma=0.001, kernel=poly .......................
[CV] ............. C=0.1, degree=2, gamma=0.0001, kernel=poly -   0.0s
[CV] C=0.1, degree=2, gamma=0.001, kernel=poly .......................
[CV] C=0.1, degree=2, gamma=0.001, kernel=poly .......................
[CV] .............. C=0.1, degree=1, gamma=0.001, kernel=poly -   0.1s
[CV] C=0.1, degree=3, gamma=0.0001, kernel=poly ......................
[CV] .............. C=0.1, degree=1, gamma=0.001, kernel=poly -   0.2s
[CV] C=0.1, degree=3, gamma=0.0001, kernel=poly ......................
[CV] .............. C=0.1, degree=2, gamma=0.001, kernel=poly -   0.1s
[CV] C=0.1, degree=3, gamma=0.0001, kernel=poly ......................
[CV] ............. C=0.1, degree=3, gamma=0.0001, kernel=poly -   0.1s
[CV] C=0.1, degree=3, gamma=0.001, kernel=poly .......................
[CV] ............. C=0.1, degree=2, gamma=0.0001, kernel=poly -   0.2s
[CV] C=0.1, degree=3, gamma=0.001, kernel=poly .......................
[CV] ............. C=0.1, degree=3, gamma=0.0001, kernel=poly -   0.2s
[CV] ............. C=0.1, degree=3, gamma=0.0001, kernel=poly -   0.2s
[CV] C=0.1, degree=3, gamma=0.001, kernel=poly .......................
[CV] C=1, degree=1, gamma=0.0001, kernel=poly ........................
[CV] ............... C=1, degree=1, gamma=0.0001, kernel=poly -   0.1s
[CV] C=1, degree=1, gamma=0.0001, kernel=poly ........................
[CV] .............. C=0.1, degree=2, gamma=0.001, kernel=poly -   0.3s
[CV] C=1, degree=1, gamma=0.0001, kernel=poly ........................
[CV] ............... C=1, degree=1, gamma=0.0001, kernel=poly -   0.1s
[CV] .............. C=0.1, degree=2, gamma=0.001, kernel=poly -   0.4s
[CV] C=1, degree=1, gamma=0.001, kernel=poly .........................
[CV] C=1, degree=1, gamma=0.001, kernel=poly .........................
[CV] ............... C=1, degree=1, gamma=0.0001, kernel=poly -   0.1s
[CV] C=1, degree=1, gamma=0.001, kernel=poly .........................
[CV] ................ C=1, degree=1, gamma=0.001, kernel=poly -   0.1s
[CV] C=1, degree=2, gamma=0.0001, kernel=poly ........................
[CV] ................ C=1, degree=1, gamma=0.001, kernel=poly -   0.2s
[CV] ................ C=1, degree=1, gamma=0.001, kernel=poly -   0.1s
[CV] C=1, degree=2, gamma=0.0001, kernel=poly ........................
[CV] C=1, degree=2, gamma=0.0001, kernel=poly ........................
[CV] ............... C=1, degree=2, gamma=0.0001, kernel=poly -   0.2s
[CV] C=1, degree=2, gamma=0.001, kernel=poly .........................
[CV] ............... C=1, degree=2, gamma=0.0001, kernel=poly -   0.1s
[CV] C=1, degree=2, gamma=0.001, kernel=poly .........................
[CV] ............... C=1, degree=2, gamma=0.0001, kernel=poly -   0.2s
[CV] C=1, degree=2, gamma=0.001, kernel=poly .........................
[CV] ................ C=1, degree=2, gamma=0.001, kernel=poly -   0.6s
[CV] C=1, degree=3, gamma=0.0001, kernel=poly ........................
[CV] ................ C=1, degree=2, gamma=0.001, kernel=poly -   0.6s
[CV] C=1, degree=3, gamma=0.0001, kernel=poly ........................
[CV] ............... C=1, degree=3, gamma=0.0001, kernel=poly -   0.1s
[CV] C=1, degree=3, gamma=0.0001, kernel=poly ........................
[CV] .............. C=0.1, degree=3, gamma=0.001, kernel=poly -   1.4s
[CV] C=1, degree=3, gamma=0.001, kernel=poly .........................
[CV] ................ C=1, degree=2, gamma=0.001, kernel=poly -   0.7s
[CV] C=1, degree=3, gamma=0.001, kernel=poly .........................
[CV] ............... C=1, degree=3, gamma=0.0001, kernel=poly -   0.2s
[CV] C=1, degree=3, gamma=0.001, kernel=poly .........................
[CV] ............... C=1, degree=3, gamma=0.0001, kernel=poly -   0.2s
[CV] C=10, degree=1, gamma=0.0001, kernel=poly .......................
[CV] .............. C=10, degree=1, gamma=0.0001, kernel=poly -   0.1s
[CV] C=10, degree=1, gamma=0.0001, kernel=poly .......................
[CV] .............. C=0.1, degree=3, gamma=0.001, kernel=poly -   1.7s
[CV] C=10, degree=1, gamma=0.0001, kernel=poly .......................
[CV] .............. C=10, degree=1, gamma=0.0001, kernel=poly -   0.1s
[CV] C=10, degree=1, gamma=0.001, kernel=poly ........................
[CV] .............. C=10, degree=1, gamma=0.0001, kernel=poly -   0.1s
[CV] C=10, degree=1, gamma=0.001, kernel=poly ........................
[CV] ............... C=10, degree=1, gamma=0.001, kernel=poly -   0.2s
[CV] C=10, degree=1, gamma=0.001, kernel=poly ........................
[CV] ............... C=10, degree=1, gamma=0.001, kernel=poly -   0.2s
[CV] C=10, degree=2, gamma=0.0001, kernel=poly .......................
[CV] .............. C=10, degree=2, gamma=0.0001, kernel=poly -   0.2s
[CV] C=10, degree=2, gamma=0.0001, kernel=poly .......................
[CV] .............. C=0.1, degree=3, gamma=0.001, kernel=poly -   2.2s
[CV] C=10, degree=2, gamma=0.0001, kernel=poly .......................
[CV] ............... C=10, degree=1, gamma=0.001, kernel=poly -   0.3s
[CV] C=10, degree=2, gamma=0.001, kernel=poly ........................
[CV] .............. C=10, degree=2, gamma=0.0001, kernel=poly -   0.2s
[CV] C=10, degree=2, gamma=0.001, kernel=poly ........................
[CV] .............. C=10, degree=2, gamma=0.0001, kernel=poly -   0.2s
[CV] C=10, degree=2, gamma=0.001, kernel=poly ........................
[CV] .................................... C=10, kernel=linear -   6.5s
[CV] C=10, degree=3, gamma=0.0001, kernel=poly .......................
[CV] .............. C=10, degree=3, gamma=0.0001, kernel=poly -   0.5s
[CV] C=10, degree=3, gamma=0.0001, kernel=poly .......................
[CV] .............. C=10, degree=3, gamma=0.0001, kernel=poly -   0.6s
[CV] C=10, degree=3, gamma=0.0001, kernel=poly .......................
[CV] ............... C=10, degree=2, gamma=0.001, kernel=poly -   2.3s
[CV] C=10, degree=3, gamma=0.001, kernel=poly ........................
[CV] .............. C=10, degree=3, gamma=0.0001, kernel=poly -   0.6s
[CV] C=10, degree=3, gamma=0.001, kernel=poly ........................
[CV] ............... C=10, degree=2, gamma=0.001, kernel=poly -   3.1s
[CV] C=10, degree=3, gamma=0.001, kernel=poly ........................
[CV] ............... C=10, degree=2, gamma=0.001, kernel=poly -   3.7s
[CV] C=100, degree=1, gamma=0.0001, kernel=poly ......................
[CV] ............. C=100, degree=1, gamma=0.0001, kernel=poly -   0.2s
[CV] C=100, degree=1, gamma=0.0001, kernel=poly ......................
[CV] ............. C=100, degree=1, gamma=0.0001, kernel=poly -   0.2s
[CV] C=100, degree=1, gamma=0.0001, kernel=poly ......................
[CV] ............. C=100, degree=1, gamma=0.0001, kernel=poly -   0.3s
[CV] C=100, degree=1, gamma=0.001, kernel=poly .......................
[CV] .............. C=100, degree=1, gamma=0.001, kernel=poly -   0.5s
[CV] C=100, degree=1, gamma=0.001, kernel=poly .......................
[CV] .............. C=100, degree=1, gamma=0.001, kernel=poly -   0.8s
[CV] C=100, degree=1, gamma=0.001, kernel=poly .......................
[CV] .............. C=100, degree=1, gamma=0.001, kernel=poly -   0.6s
[CV] C=100, degree=2, gamma=0.0001, kernel=poly ......................
[CV] ................ C=1, degree=3, gamma=0.001, kernel=poly -   7.8s
[CV] C=100, degree=2, gamma=0.0001, kernel=poly ......................
[CV] ............. C=100, degree=2, gamma=0.0001, kernel=poly -   0.6s
[CV] C=100, degree=2, gamma=0.0001, kernel=poly ......................
[CV] ................ C=1, degree=3, gamma=0.001, kernel=poly -   8.2s
[CV] C=100, degree=2, gamma=0.001, kernel=poly .......................
[CV] ............. C=100, degree=2, gamma=0.0001, kernel=poly -   0.6s
[CV] C=100, degree=2, gamma=0.001, kernel=poly .......................
[CV] ................ C=1, degree=3, gamma=0.001, kernel=poly -   8.7s
[CV] C=100, degree=2, gamma=0.001, kernel=poly .......................
[CV] .................................... C=10, kernel=linear -  13.5s
[CV] C=100, degree=3, gamma=0.0001, kernel=poly ......................
[CV] ............. C=100, degree=2, gamma=0.0001, kernel=poly -   0.7s
[CV] C=100, degree=3, gamma=0.0001, kernel=poly ......................
[CV] .................................... C=10, kernel=linear -  13.7s
[CV] C=100, degree=3, gamma=0.0001, kernel=poly ......................
[CV] ............. C=100, degree=3, gamma=0.0001, kernel=poly -   1.8s
[CV] C=100, degree=3, gamma=0.001, kernel=poly .......................
[CV] ............. C=100, degree=3, gamma=0.0001, kernel=poly -   2.2s
[CV] C=100, degree=3, gamma=0.001, kernel=poly .......................
[CV] ............. C=100, degree=3, gamma=0.0001, kernel=poly -   2.4s
[CV] C=100, degree=3, gamma=0.001, kernel=poly .......................
[CV] .............. C=100, degree=2, gamma=0.001, kernel=poly -   6.0s
[CV] C=0.1, gamma=0.0001, kernel=sigmoid .............................
[CV] .................... C=0.1, gamma=0.0001, kernel=sigmoid -   0.2s
[CV] C=0.1, gamma=0.0001, kernel=sigmoid .............................
[CV] .................... C=0.1, gamma=0.0001, kernel=sigmoid -   0.2s
[CV] C=0.1, gamma=0.0001, kernel=sigmoid .............................
[CV] .................... C=0.1, gamma=0.0001, kernel=sigmoid -   0.1s
[CV] C=0.1, gamma=0.001, kernel=sigmoid ..............................
[CV] ..................... C=0.1, gamma=0.001, kernel=sigmoid -   0.1s
[CV] C=0.1, gamma=0.001, kernel=sigmoid ..............................
[CV] ..................... C=0.1, gamma=0.001, kernel=sigmoid -   0.1s
[CV] C=0.1, gamma=0.001, kernel=sigmoid ..............................
[CV] ..................... C=0.1, gamma=0.001, kernel=sigmoid -   0.1s
[CV] C=1, gamma=0.0001, kernel=sigmoid ...............................
[CV] ...................... C=1, gamma=0.0001, kernel=sigmoid -   0.2s
[CV] C=1, gamma=0.0001, kernel=sigmoid ...............................
[CV] ...................... C=1, gamma=0.0001, kernel=sigmoid -   0.2s
[CV] C=1, gamma=0.0001, kernel=sigmoid ...............................
[CV] ...................... C=1, gamma=0.0001, kernel=sigmoid -   0.2s
[CV] C=1, gamma=0.001, kernel=sigmoid ................................
[CV] ....................... C=1, gamma=0.001, kernel=sigmoid -   0.1s
[CV] C=1, gamma=0.001, kernel=sigmoid ................................
[CV] ....................... C=1, gamma=0.001, kernel=sigmoid -   0.1s
[CV] C=1, gamma=0.001, kernel=sigmoid ................................
[CV] ....................... C=1, gamma=0.001, kernel=sigmoid -   0.1s
[CV] C=10, gamma=0.0001, kernel=sigmoid ..............................
[CV] ..................... C=10, gamma=0.0001, kernel=sigmoid -   0.2s
[CV] C=10, gamma=0.0001, kernel=sigmoid ..............................
[CV] ..................... C=10, gamma=0.0001, kernel=sigmoid -   0.2s
[CV] C=10, gamma=0.0001, kernel=sigmoid ..............................
[CV] ..................... C=10, gamma=0.0001, kernel=sigmoid -   0.2s
[CV] C=10, gamma=0.001, kernel=sigmoid ...............................
[CV] ...................... C=10, gamma=0.001, kernel=sigmoid -   0.1s
[CV] C=10, gamma=0.001, kernel=sigmoid ...............................
[CV] ...................... C=10, gamma=0.001, kernel=sigmoid -   0.1s
[CV] C=10, gamma=0.001, kernel=sigmoid ...............................
[CV] ...................... C=10, gamma=0.001, kernel=sigmoid -   0.1s
[CV] C=100, gamma=0.0001, kernel=sigmoid .............................
[CV] .................... C=100, gamma=0.0001, kernel=sigmoid -   0.2s
[CV] C=100, gamma=0.0001, kernel=sigmoid .............................
[CV] .................... C=100, gamma=0.0001, kernel=sigmoid -   0.2s
[CV] C=100, gamma=0.0001, kernel=sigmoid .............................
[CV] .................... C=100, gamma=0.0001, kernel=sigmoid -   0.2s
[CV] C=100, gamma=0.001, kernel=sigmoid ..............................
[CV] ..................... C=100, gamma=0.001, kernel=sigmoid -   0.1s
[CV] C=100, gamma=0.001, kernel=sigmoid ..............................
[CV] ..................... C=100, gamma=0.001, kernel=sigmoid -   0.1s
[CV] C=100, gamma=0.001, kernel=sigmoid ..............................
[CV] ..................... C=100, gamma=0.001, kernel=sigmoid -   0.1s
[CV] .............. C=100, degree=2, gamma=0.001, kernel=poly -  10.1s
[CV] .............. C=100, degree=2, gamma=0.001, kernel=poly -  18.6s
[CV] ................................... C=100, kernel=linear -  32.8s
[CV] ............... C=10, degree=3, gamma=0.001, kernel=poly -  26.0s
[CV] ................................... C=100, kernel=linear -  43.8s
[CV] ................................... C=100, kernel=linear -  47.6s
[CV] ............... C=10, degree=3, gamma=0.001, kernel=poly -  45.1s
[CV] ............... C=10, degree=3, gamma=0.001, kernel=poly -  44.6s
[CV] .............. C=100, degree=3, gamma=0.001, kernel=poly - 1.4min
[CV] .............. C=100, degree=3, gamma=0.001, kernel=poly - 2.1min
[CV] .............. C=100, degree=3, gamma=0.001, kernel=poly - 2.7min
[Parallel(n_jobs=-1)]: Done 144 out of 144 | elapsed:  2.9min finished
学習が終了しました。
学習データをプロットします
ベストデータ: 学習器= SVC(C=10, cache_size=200, class_weight=None, coef0=0.0,
  decision_function_shape='ovr', degree=3, gamma=0.001, kernel='poly',
  max_iter=-1, probability=False, random_state=None, shrinking=True,
  tol=0.001, verbose=False)
CCr Data_test から 500 件の分類テストを実行します。
テストデータの準備が整いました。
正解率= 0.914
レポート=
             precision    recall  f1-score   support

         G1       0.95      0.92      0.93        96
         G2       0.87      0.92      0.89        71
        G3a       0.92      0.90      0.91        77
        G3b       0.91      0.89      0.90       110
         G4       0.91      0.97      0.94       122
         G5       1.00      0.79      0.88        24

avg / total       0.92      0.91      0.91       500

テストデータをプロットします

このようにグリッドサーチが行われ、最終的にベストの正解率は0.914となりました。デフォルトパラメータのSVMでは正解率0.617であったことを考えるとかなり改善しているとみてよいでしょう。

Discussion

今回はcross validationとgrid searchの手法を学びました。
grid searchの方はやっていることは(実行時間はかかりますが)わかりやすく、最もよい学習結果を達成する学習パラメータを探索するということになるようです。問題は「特定のデータ」に対する「特定の学習器の」最適化であって、これを一般化するのは容易ではないということです。実際に必要となるタスクにおいて、データの方は固定されていてただただ分類能のよい学習器を作ることが目的であればこれでも構わないわけですが、例えばデータが経時的に積み足されていく場合や、データそのものは重要ではなく学習器の方の開発を行うような場合にはgrid searchの手法では不十分なところが残るように思いました。

また、cross validationの方はさらに謎が残ります。教科書と同様のコードを実行してみたところ、分割したそれぞれの組についての正解率が出せましたが、そもそも何を検証する仕組みなのかが判然としませんでした。

  1. データの偏りがあるかどうかを検証するのか?
  2. 学習器のアルゴリズムの良し悪しを検証するのか?
  3. 学習の安定性(データの違いによる推測の偏りの有無)を検証するのか?

1.に相当する事象として、データの最初の方と最後の方が全く異質な場合も分割ごとの結果の振れ幅が大きくなるのだと思いますが、手法の目的としてはおそらく3.なんでしょうね。過学習になりやすい学習セットを作ってしまうと、cross validationでテストデータによる正解率の上下変動が大きくなるのだと思います。正解率の分散が一定以上だとダメ、みたいに使うのでしょうか。

今回達成したこと

  • cross validationとgrid searchの手法を学び、自作簡易ライブラリに実装しました。

参考文献

  1. クジラ飛行机, Pythonによるスクレイピング&機械学習[開発テクニック], ソシム株式会社, 2016