毎日テキストマイニング

180日間、毎日テキストマイニングをするブログです

2018/8/13【51日目】ランダムフォレストの正解率を上げていきたいので混合行列を見てみた

昨日、やっと福岡聖菜tweetを当てることができましたが、全部は当てることができなかったのでもう少し正解率をあげたいと思います。 ですが、そもそも自分で作ったモデルがどのくらいの正解率を持っているのかを知る必要がありそうですね。

モデルの検証

モデルの正解率を調べるにはホールドアウト法k分割交差検証という2種類の方法があるそうです。

ホールドアウト法はデータの20%〜40%ほどを分析に使わずに(ホールドアウト)、その使わなかった分のデータで学習後にテストすることだそうです。

k分割交差検証はデータをk個に分割し、順番にテストしていく方法のようです。k分割交差検証の方が信頼度が高いのでよく使われますが、計算に時間がかかるそうです。

ひとまず、k分割交差検証をやっていきます。

20分ほど必死こいてk分割交差検証のコードを書いていましたが、途中でscikit-learnを使えば、1行でかけることが判明しました。さすがフレームワーク

from sklearn.model_selection import cross_val_score
print(cross_val_score(forest, train_data_features, train['name_int'], cv=10))

k交差検証法を利用できるcross_val_scoreをimportして、出力する際に、

  • モデル名
  • テストデータ
  • 答え
  • 何分割するか

を指定するだけです。簡単ですね。実行結果がこちら。

[ 0.97014925  0.960199    0.96517413  0.97014925  0.975       0.965
  0.96482412  0.9798995   0.95979899  0.96984925]

ほぼ、9割5分。今の時点で十分高いような気がしますね。。。。一応20分割したものはこちらです。

[ 0.97029703  0.97029703  0.96039604  0.97029703  0.97029703  0.96039604
  0.97        0.97        0.96        0.96        0.95        0.96        0.96
  0.98        0.96969697  0.96969697  0.95959596  0.96969697  0.97979798
  0.97979798]

変わらず、ほぼ9割5分。

混合行列

正解率は高いのですが、もともと福岡聖菜tweet数が全体から見たら少ないので、全体を0で出してしまえばこのくらいの正解率になるような気がします。こう言った問題を解決するのが混合行列という検証法だそうです。混合行列はそれぞれの正解のやり方、はずれのやり方を表すそうです。文章でいわれてもチンプンカンプンなので、実装してみます。

混合行列の実装

まず、特徴量をテスト用に分割します。データの分割はtrain_test_splitを使えばいいそうです。ホールドアウト法もこのように分割して使うそうです。今回は本番用とテスト用にデータを半分に分けています(test_size = 0.5)。

from sklearn.model_selection import train_test_split

train_X, test_X, train_y, test_y = train_test_split(train_data_features, 
                               train['name_int'],
                               test_size = 0.5)

分割できたか見てみます。

train_X.shape[0]
1000
test_y.shape[0]
1000

もともと2000あったデータが1000ずつに分解できていますね。

テスト用のデータができたところで、混合行列を出力したいと思います。 混合行列はscikit-learnのconfusion_matrixを使えば良さそうです。学習して出した[’name_int']と元の['name_int']を比べています。

from sklearn.metrics import confusion_matrix
y_preds = forest.predict(train_X)
confusion_matrix(test_y, y_preds)

実行結果。

array([[926,  31],
       [ 43,   0]])

それぞれの結果はこんな感じです。

  • 左上:TP(True Positive)正しく陽性と判定できた数値
  • 右上:TP(True Negative)正しく陰性と判定できた数値
  • 左下:FP(False Positive)本来は陰性なところを、誤って陽性と判定してしまった数値
  • 右下:FN(False Negative)本来は陽性なところを、誤って陰性と判定してしまった数値

何を言っているのかよくわからないですね。今回の場合に翻訳するとこんな感じです。

  • 左上:TP(True Positive)正しく福岡聖菜ではないと判定できた数値
  • 右上:TP(True Negative)正しく福岡聖菜と判定できた数値
  • 左下:FP(False Positive)本来は福岡聖菜なところを、誤って福岡聖菜ではないと判定してしまった数値
  • 右下:FN(False Negative)本来は福岡聖菜ではないところを、誤って福岡聖菜と判定してしまった数値

となります。上の結果を見ると、43件の福岡聖菜の呟きを福岡聖菜ではないと判定してしまったようです。正解数が955件なので、955 / 1000 できっかり9割5分5厘ですね。

明日はこの43という数字を減らしていきたいと思います。

今日の結果

今日のAKBメンバーによる呟きは60件でした。 改めてありがとう、という感じのtweetが多いです。 f:id:rimt:20180814022011p:plain

'嬉しい': 8, 'ない': 3, '楽しい': 3, 'かわいい': 3, 'すごい': 2, '可愛い': 2, '短い': 2, '凄い': 2, 'やばい': 2, '寂しい': 1, '早い': 1, '暑い': 1, '涼しい': 1, '長い': 1, '新しい': 1, '美味しい': 1, 'くさい': 1, '良い': 1, '素晴らしい': 1, '遅い': 1, '悔しい': 1, 'たのしい': 1
'カンシャサイ': 17, '浴衣': 13, 'コンサート': 11, '皆さん': 10, '日': 10, '今日': 10, 'さん': 9, '嬉しい': 8, 'ん': 8, 'ランク': 8, '外': 7, '私': 7, 'ちゃん': 7, 'こと': 7, 'アクシュカイ': 6, 'エーケービーフォーティーエイト': 6, '応援': 6, '公演': 6,
'する': 21, 'カンシャサイ': 17, '浴衣': 13, 'コンサート': 11, 'くださる': 11, '皆さん': 10, '日': 10, '今日': 10, 'さん': 9, '嬉しい': 8, 'ん': 8, 'ランク': 8, 'なる': 8, '外': 7, '私': 7, 'ちゃん': 7, 'こと': 7, 'れる': 7, 'くれる': 7,