以下のような疑問にお答えします
- 混同行列 (Confusion matrix)のTP、TN、FP、FNの意味がわからない
- 「正解率」「適合率」「再現率」「F値」って何?
上記のような疑問に、歴20年の現役エンジニアが回答します。
混同行列について解説
機械学習の分類結果の精度を検証するために、混同行列 (Confusion matrix)が主に使われます。混同行列をつかうことにより、正しく選別された件数、および間違って選別された数を比較できます。比較結果を元に機械学習で作成されたモデルを検証します。
しかし、図のTP、TN、FP、FNの意味は、説明されても分からないことが多くないですか?これを人に説明しても「なんのことだからさっぱり分からないよ」と言われてしまいました。
この記事では、「オタクかどうか判断するカメラアプリ」を例に以下を解説します。
・TP、TN、FP、FN
・正解率
・本当に正解率を鵜呑みにして良いの?
・正解ラベルが少ないときの検証について
オタクかどうか判断するカメラアプリで混同行列を解説
そこで、「オタクかどうか判定」するカメラアプリを例に解説します。
カメラアプリの前提条件:
- カメラアプリは、機械学習で言うところの学習済みモデルが内蔵されている
- カメラアプリは、カメラで人物を撮影すると「オタク」「非オタク」を出力する
- 分類は、「オタク(正)」「非オタク(負)」の2値問題とする
- 学習データには、着ている服、ズボン、スカートなどの見た目の特長情報がある
- 「正」=「Positive(陽性)」、「負」=「Negative(陰性)」と呼ぶことにする
真陽性・TP(True-Positive)
ポジティブに分類すべきものをちゃんとポジティブに分類できた件数のこと指します。
カメラアプリの例だと、「オタク(陽性)」をカメラアプリが正しく「オタク」と判定できた件数をします。
「TP」を思い出す方法としては、
カメラアプリの判定は「オタク(Positive)」で正解だった(つまりTRUE)と考えると分かりやすいかもしれません。
ポイント
頭文字がTならカメラアプリの正解、Fなら「間違え」と考えるとイメージしやすいです。
真陰性・TN(True-Negative)
ネガティブに分類すべきものちゃんとネガティブに分類できた件数を指します。
カメラアプリの例だと、「非オタク(負)」をカメラアプリが正しく「非オタク」と判定できた件数をします。
「TN」を思い出す方法としては、
カメラアプリの判定は「非オタク(負・陰性)」で正解だった(つまりTRUE)と考えると分かりやすいかもしれません。
偽陽性・FP(False-Positive)
頭文字にFがつくものがイメージしづらいですが・・・。
偽陽性は、ネガティブに分類すべきものを間違ってポジティブに分類してしまった件数を指します。
「FP」を思い出す方法としては、
カメラアプリが「オタク(陽性)」と判定したら間違って(False)いた。つまり、正解はネガティブだった!と考えると良いかもしれません。
偽陰性・FN(False-Negative)
これも頭文字にFがつくのでイメージしづらい・・・
これも、解決する!・・・はず
偽陰性とは、ポジティブと分類すべきものを間違ってネガティブに分類してしまった件数を指します。
カメラアプリの例だと、カメラアプリが「非オタク(陰性)」と判定したら間違っていた(False)。つまり正解は、ポジティブだったということです。
分類結果を検証する4つの手段
手段1・正解率 (Accuracy)
正解率 (Accuracy) とは、以下の式で計算して出た割合です。
Accuracy = (TP + TN) / (TP + TN + FP + FN)
正しく、ポジティブ、ネガティブに分類できた割合で表されます。正解率の値が高いほど、性能が良いモデルと言われます。ただし、正(オタク)、負(非オタク)のデータが同じ割合の場合のみです。
もし、正のデータが極端に少ないケースの場合は、正解率は当てになりません。
その理由を次に述べます。
正解率が役に立たないケース
もし、カメラの学習状態がポンコツで、予測結果を全て「オタクじゃない(負)」と返した場合を考えてみます。
オタク(正ラベル)が10人
非オタク(負ラベル)が90人だったケースを考えます。
このとき混同行列に書くと以下の通りになります。
TP・・・0
TN・・・90
FP・・・0
FN・・・10
正解率が90%になってしまいます。
つまり、当てずっぽうで判定しても正解率が90%なのです!
正のデータが極端に少ないときに、
正解率が高いはオカシイよね?
だから正解率が必ずしも当てになりません。
そんなときに役立つのが次に紹介する「検出率」「再現率」「F値」です。
手段2・適合率 (Precision)
適合率 (Precision) とは、ポジティブに分類されたデータのうち、実際にポジティブであったデータの割合を示し、以下の式で表されます。
Precision = TP / (TP + FP)
先ほどの「全て負で判定されるポンコツカメラアプリ」の値を当てはめてみます。
TP・・・0
TN・・・90
FP・・・0
FN・・・10
すると、0になってしまいます。
全く「適合していない」ことがわかります。
手段3・再現率 (Recall)
再現率(Recall) とは、ポジティブに分類すべきデータを、正しくポジティブに分類できたデータの割合を示し、以下の式で表されます。
Recall = TP / (TP + FN)
同じくポンコツカメラアプリの評価結果を当てはめてみます。
TP・・・0
TN・・・90
FP・・・0
FN・・・10
同じく0になってしまいます。再現性も全くないということですね。
手段4・F値
ポンコツカメラアプリの例であれば、適合率、再現率ともに0になるため、当てにならないモデルであることが分かりました。
では、適合率、再現率ともに0でない実数だったらどうなるのでしょうか?どっちの数値を信用したらよいの?
適合率、再現率のどちらを適用したら良いかは、業務内容によって変わるみたいだよ。だから、最終的に自分で判断するしかないんだ。
なるほど、検証に使うなら、二つを合わせて平均を取ればいいじゃない?
そうはいかないんだ。
仮に適合率=1、再現率=0だったら平均は0.5になるよ。
それだと適合率、再現率のどっちを使って良いかわからないよね。
そこでF値を使った指標があります。
F値とは
F値(F-measure, F-score, F1 Score とも呼ばれる) とは、適合率(Precision) と再現率(Recall) のバランスが保たれているかの指標です。つまり、適合率は高くても、再現率が低いモデルでないか、またその逆がないかといった検証を示します。
式は以下の通りになります。
$$F = \frac{2}{\frac{1}{precision}+\frac{1}{recall}}$$
F値が高いほどバランスが取れているモデルになります。
最終的に「適合率」「再現率」「F値」から検証
最終的には、「適合率」「再現率」「F値」から検証します。
どの検証を選択するかは、業務内容によって変わってくるようです。
Kaggleのコンペの場合は、評価方法が指定されていることが多いので、指定された方法で評価します。
実際にコードを書いて解説するよ
Pythonで以下の求め方のサンプルを記載します。
・混同行列
・正解率
・適合率
・再現率
・F値
#乳がんのデータを使って学習
#ロジステック回帰の学習結果を検証する
import pandas as pd
from sklearn.datasets import load_breast_cancer
dataset = load_breast_cancer()
#説明変数と目的変数を分ける
X = pd.DataFrame(dataset.data, columns=dataset.feature_names)
y = pd.Series(dataset.target, name='y')
X.join(y).head()
import numpy as np
from sklearn.preprocessing import StandardScaler
from IPython.core.display import display
from sklearn.linear_model import LogisticRegression
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
# holdout
X_train,X_test,y_train,y_test=train_test_split(X,
y,
test_size=0.3,
random_state=3)
#ロジテック回帰で学習
clf = LogisticRegression(random_state=1).fit(X_train, y_train)
#予測
y_pred = clf.predict(X_test)
from sklearn.metrics import confusion_matrix, accuracy_score, precision_score, recall_score, f1_score
from sklearn.metrics import roc_curve, auc
import matplotlib.pyplot as plt
#混同行列
print('confusion matrix = \n', confusion_matrix(y_true=y_test, y_pred=y_pred))
#tn, fp, fn, tp = confusion_matrix(y_true=y_test, y_pred=y_pred).ravel()
#print("tn=%f fp=%f fn=%f tp=%f" % (tn, fp, fn, tp))
#本家では上記のように書いてあるが、本当に正しいのか?
#tp, fn, fp, tnの順番が正しい気がする・・・
#https://scikit-learn.org/stable/modules/generated/sklearn.metrics.confusion_matrix.html
#正解率
ans = accuracy_score(y_test, y_pred)
print("正解率(accuracy) = " + str(ans))
#適合率
ans = precision_score(y_test, y_pred)
print("適合率(precision) = " + str(ans))
#再現率
ans = recall_score(y_test, y_pred)
print("再現率(recall) = " + str(ans))
#F値(f1スコア)
#F1 = 2 * (precision * recall) / (precision + recall)
ans = f1_score(y_test, y_pred)
print("F1スコア = " + str(ans))
#AUCスコア
Y_score = clf.predict_proba(X_test)# 検証データがクラス1に属する確率を出す
Y_score = Y_score[:,1]
#print(Y_score)
fpr, tpr, thresholds = roc_curve(y_true=y_test, y_score=Y_score)
print('AUCスコア %0.3f' % auc(fpr, tpr))
plt.plot(fpr, tpr, label='roc curve (area = %0.3f)' % auc(fpr, tpr))
plt.legend()
plt.xlabel('false positive rate')
plt.ylabel('true positive rate')
plt.show()
この記事を書くのに役だった参考資料
AIジョブカレの授業
AIジョブカレは、AIに特化したプログラミングスクールです。
決まった日に教室に通う形式のスクールで機械学習講座の中で最も料金が安いといえる。
全部で8回の授業(1回 2時間)で業務で使うレベルの機械学習の知識を得られます。
もちろん、今回取り上げた分類の検証についても授業でも学習します。
やさしく学ぶ 機械学習を理解するための数学のきほん
大学レベルの数学を知らなくても問題なく読みすすめることができます。
回帰問題、ロジスティック回帰など丁寧に解説していて、かつ、ライブラリーを使わない方法でpythonを使った実装例があるため大変参考になります。数学や統計学で挫折してしまった人におすすめの本といえます。
分類問題の検証についても取り上げています。
まとめ
分類において混合行列の扱いは、慣れないと難しいです。
しかし、業務では必ず使われるため是非抑えておきましょう。
\IT未経験者からのサポートあり!転職サービス3選!!/
サービス名 | |||
---|---|---|---|
未経験 | 未経験OK | 未経験の転職専用 | 経験者向け |
公開の求人数 | ITエンジニア全体で1万件以上 ITエンジニア未経験で600件以上 |
未公開 | 5,000件以上 |
利用対象 | 全職種 | IT特化 | IT特化 |
特徴 | ✓誰もが知る転職サービス ✓経歴を登録しておくとオファーが来る |
✓企業担当者と条件交渉 ✓スキルの身につく企業を紹介 |
✓IT専門のエージェントが対応 ✓転職成功すると年収200万円以上の大幅アップがある |
転職サポート内容 |
|
|
|
公式サイト | リクナビネクスト | テックゲート | レバテックキャリア |