scikit-learnを用いた機械学習の初歩③~モデルの評価(追記)~

2018/05/07

python scikit-learn プログラミング

はじめに

前回の記事ではモデルの評価を以下のようにしていました。

x_pred =knn.predict(X_test)#テストデータを学習モデルにセット
x_judge = x_pred == x_test #予測したデータと答えが一致しているか
true_count = len(np.where(x_judge==True)[0])#正解した数
print(x_judge)
print(true_count/len(x_judge))#正答率

調べてみるとscikit-learn内にaccuracy_scoreやclassification_reportと呼ばれる評価関数があったので、それらを使ってみました。
↓前回記事

accuracy_scoreの使い方

これを使いことで正解率や正解数を見ることができます。
accuracy_scoreは以下のようにimportします。
from sklearn.metrics import accuracy_score
accuracy_score(y_true, y_pred, normalize=True, sample_weight=None)
各引数の説明は以下の通りです。
y_true正解ラベル
y_pred予測した結果
normalizaTrueにすると正解率
Falseにすると正解数が表示
(デフォルト:True)

実際に前回つかったx_test,x_predを表示させてみます。
print(x_test)
print(x_pred)
print (accuracy_score(x_test, x_pred))
print (accuracy_score(x_test, x_pred,normalize=False))
表示結果を図1に示します。図1を見ると1か所だけ誤った判定をしています。なので、正解率としては96.7%、正解数は29個と出力がされています。
図1:accuracy_score実行結果

classification_reportの使い方

この関数を使うことでPrecision、Recall、F値、support(正解ラベルのデータの数)が分かります。
classification_reportは以下のようにimportします。
from sklearn.metrics import classification_report
classification_report(y_true, y_pred, labels=None, target_names=None, sample_weight=None, digits=2)

各引数の説明は以下の通りです。
y_true正解ラベル
y_pred予測した結果
target_names分類するデータ名
(デフォルト:None)

Precision、Recall、F値について

Precision、Recall、F値について分からなかったので、下記のサイトを参考にしました。
Precision、Recall、F値について説明する際に以下の表を用います。
真の結果
予想結果
TPFP
FNTN
ここでTPはTrue Positive(予想が正(Positive)で結果と一致(True))、FPはFalse Positive(予想が正で不一致(False))、FNはFalse Negative(予想が負(Negative)で結果と不一致)、TNはTrue Negativi(予想が負で正解と一致)の略みたいです。

上記の表を用いてPrecision、Recall、Fは以下のように表すことができます。

Precision

\begin{equation} Precision = \frac{TP}{TP+FP} \end{equation}
式を見てわかる通り予想結果が正の場合に対する正解率を表しています。

本の落丁を例として説明すると、この値が大きいということは、本当は落丁している本なのに、正しく製本できていると判断された数(FP)が少ないということになります。

この評価指標はFN(正しく製本できているのに、落丁していると判断)よりFP(落丁しているのに、正しく製本できていると判断)があっては困る場合に重要視します。

本の例では、落丁しているものが正しく製本できていると判断されると、お客様からクレームが来てしまうので、このPrecisionを重要視します。言い換えると正確性を重要視する指標です。また、後述するRecallとはトレードオフの関係性があります。

Recall

\begin{equation} Recall = \frac{TP}{TP+FN} \end{equation}
こちらは真の結果が正の場合に対する正解率を表しています

病気を例として説明すると、この値が大きいということは本当は病気なのに、健康と診断された数(FN)が少ないということになります。この評価指標はFP(病気じゃないのに病気であると診断)よりFN(病気であるのに、病気でないと診断)があっては困る場合に重要視します。

病気の例では、病気であるのに病気で無いと診断されるのは問題なので、このRecallを重要視します。言い換えると網羅性を重要視する指標です。

F値

\begin{equation} F-measure = \frac{2 \cdot Recall \cdot Recall}{Recall + Precision} \end{equation}
PrecisionとRecallがトレードオフの関係あるため、F値は
適合率と再現率の調和平均としています。
調和平均としている理由については下記記事の説明が分かりやすいと思いました。

ちなみに上記の表を用いて正解率は次のように表すことが出来ます。

\begin{equation} Accuracy = \frac{TP + TN}{TP + FP + PN + TN} \end{equation}
個人的には正解率だけの評価でいいのではないかと思っていたのですが、いまさら聞けない機械学習の評価関数
を読んで、正解率だけで評価した場合の問題点が何となく理解できました。

すべてのデータを負と評価するモデルに対して、正解ラベルがすべて負だったら精度が100%のモデルと評価することが出来ます。しかし、このモデルに正解ラベルがすべて正のデータを入力すると一気に精度が悪くなってしまいます。なので、他の評価指標が必要みたいです。

(補足)TP、FP、FN、TNについてのわかりやすい画像

TP、FP、FN、TNについてのわかりやすい画像を見つけたので、紹介します。
こちらより引用
初めて知ったのですが、FPのことをType1エラーやαエラーといい、FNのことをType2エラーやβエラーというみたいです。

classification_report実行結果

少し前置きが長くなってしまいましたが、下記コードを実行してclassification_reportの出力結果を確認したところ図2のようになりました。
print(x_test)
print(x_pred)
print (classification_report(x_test, x_pred,target_names=iris_dataset["target_names"]))

図2:classification_report実行結果
今度の例では2か所で間違えています(本来は1なのに2と予想)。
setosa(0番)はすべて一致していることが分かります。

verisicolor(1番)のrecallが1より小さく、0.83となっています。すなわち本当はversicolorなのに違うものと診断されることが多いということが分かります。実際に数えてみるとTP(予想が1で結果も1である個数)は10個、FN(予想は1以外で、結果が1となる個数)
は2個なので、(2)式に当てはめると0.83となります。

また、virginica(2番)はprecisionが1より小さくなっています。すなわち本当はvirginicaではないのにvirginicaと診断されることが多いということが分かります。
実際に数えてみるとTP(予想が2で結果も2である個数)は7個で、FP(予想は2なのに、結果は2以外である個数)は2個なので、(1)式に当てはめると0.78となります。

まとめ

scikit-learn内にaccuracy_scoreやclassification_reportと呼ばれる評価関数を使って、モデルの評価を行いました。また、Recall、Precision、F値の違いについて紹介しました。

自己紹介

はじめまして 社会人になってからバイクやプログラミングなどを始めました。 プログラミングや整備の記事を書いていますが、独学なので間違った情報が多いかもしれません。 間違っている情報や改善点がありましたらコメントしていただけると幸いです。

X(旧Twitter)

フォローお願いします!

ラベル

QooQ