クロスバリデーションを試してみよう

どうもおはこんばんにちは。マタキチです。
最近になって気がつきました。職場のクールビズが終了していたことに。確かにクールビズしなくてもクールな気温になってきましたものね。そんな今日この頃です。

pythonで機械学習、スクレイピングを勉強しているので記述していきたいと思います。間違いありましたらご指摘いただけたら幸いです。

学習データを検証する

モデルの妥当性を検証する方法の1つに、「クロスバリデーション(交差検証)」というものがあります。クロスバリデーションとは最初に全てのデータを訓練データとテストデータに分解して、訓練データを用いて学習を行い、テストデータを用いて学習の妥当性を検証する手法です。今回はクロスバリデーションの中のK分割交差確認をしてみたいと思います。

k分割交差確認の考え方

①集合Xを、A、B、Cに分割
②Aをテストデータ、残りB、Cを訓練データとして分類精度s1を求める。
③Bをテストデータ、残りA、Cを訓練データとして分類精度s2を求める。
④Cをテストデータ、残りA、Bを訓練データとして分類精度s3を求める。
⑤分類精度s1、s2、s3の平均を分類精度とする。

それではコードを書いていきましょう。今回使用するデータは前回記事のデータを使用します。(https://note.mu/matakichi32/n/n0e516831052b

クロスバリデーション

from sklearn import svm, metrics
import random, re

lines = open('iris.csv', "r", encoding="utf-8").read().split("\n")
f_tonum = lambda n : float(n) if re.match(r'^[0-9\.]+$', n) else n
f_cols = lambda li : list(map(f_tonum, li.strip().split(',')))
csv = list(map(f_cols, lines))
del csv[0]
random.shuffle(csv)

#データをK分割する
K = 5
csvk = [ [] for i in range(K) ]
for i in range(len(csv)):
   csvk[i % K].append(csv[i])

#リストを訓練データとラベルに分割
def split_data_label(rows):
   data = []; label =[]
   for row in rows:
       data.append(row[0:4])
       label.append(row[4])
   return (data, label)

#正解率を求める
def calc_score(test, train):
   test_f, test_l = split_data_label(test)
   train_f, train_l = split_data_label(train)
   clf = svm.SVC()
   clf.fit(train_f, train_l)
   pre = clf.predict(test_f)
   return metrics.accuracy_score(test_l, pre)

#K分割したデータについて正解率を求める
score_list = []
for testc in csvk:
   trainc = []
   for i in csvk:
       if i != testc: trainc += i
   sc = calc_score(testc, trainc)
   score_list.append(sc)
print("各正解率=", score_list)
print("平均正解率=", sum(score_list) / len(score_list))

こちら実行結果です。

スクリーンショット 2019-10-17 22.30.37

5分割したデータそれぞれを検証して平均正解率がでています。k分割交差確認の結果も十分だと思います。

まとめ

scilit-learnに最初から用意してあるメソッドを使用するともっと簡単に確認することもできるのでそちらも試してみたいと思います。以上ですーーー。

いいなと思ったら応援しよう!