機械学習の評価指標

#はじめに

研究で医療データを扱うことが多く、よく使用する評価指標をまとめました。簡単なものばかりですが、自分のメモとして残しておきますので少しでも参考になればと思います。知っている人は特に読む必要は無いようなことばかりですのでこの記事はスルーしてください。


##混同行列 (Confusion Matrix)
簡単に言うと、テストデータに対する予測を表にまとめたものです。
まず、「病気である」と判断されたものを**Positive (陽性)**、「病気でない」と判断されたものを**Negative (陰性)** とします。一般的に疾患がある方を1(Positive)とする傾向があります。

|- | 検査(陽) | 検査(陰) | 
|:----: |:------:|:------:|
| **診断(陽)**| TP  | FN |
| **診断(陰)**     | FP | TN  |


Confusion Matrix は大きく以下の４グループに分けることができます。

- **TP(True Positive :真陽性)** : 検査も診断も陽性と判定した個数

- **TN(True Negative :真陰性)** : 検査も診断も陰性と判定した個数

- **FN(False Negative :偽陰性)**　: 検査は陰性と判定したが診断は陽性と判定されたした個数

- **FP(False Positive :偽陽性)**　: 検査は陽性と判定したが診断は陰性と判定された個数


また、Confusion Matrix はsklearnで簡単で作成できます。

```.python
from sklearn.metrics import confusion_matrix

cm = confusion_matrix(y_true, y_pred)
print(cm)
 ```
*y_true:正解ラベル, y_pred:テストの予測クラス
*この時、各軸は各クラスの値をソートした順番になります。順番には十分気をつけて下さい。

|- | 検査(N) | 検査(P) | 
|:----: |:------:|:------:|
| **診断(N)**| TN  | FP |
| **診断(P)**     | FN | TP  |

順番を変更したい際は、引数に`labels`で指定して下さい。

```.python
confusion_matrix(y_true, y_pred, labels=['1', '0'])
```

|- | 検査(P) | 検査(N) | 
|:----: |:------:|:------:|
| **診断(P)**| TP  | FN |
| **診断(N)**     | FP | TN  |


TP, TN, FP, FN の個数を取得する方法

```.python
cm = confusion_matrix(y_true, y_pred)
tn, fp, fn, tp = cm.flatten()
```
*ただしこの場合は、0 or 1 分類で、0を陰性としている場合である。

##評価指標




- [x] **Accuracy (正確度)**

```.math
Accuracy = \frac{TP + TN}{TP + FN + TN + FP}
```




- [x] **Sensitivity (感度)** 

  病気の人を正しく病気と判断できた割合。言い換えると、病気の人を見逃さなかった割合。再現率(recall)とも言う。感度が高い検査は、検診など病気の有無を調べる際に有効(**除外診断**)。

```.math
Sensitivity = \frac{TP}{TP + FN}
```

- [x] **Specificity (特異度)** 

  病気でない人を病気でないと正しく判断できた割合。特異度が高い検査は、病気を確定する検査で有効(**確定診断**)。


```.math
Specificity = \frac{TN}{TN + FP}
```


- [x] **PPV(Positive Predictive Value :陽性的中率)** 

検査で陽性と判断されている中で、実際に病気の人の割合。


```.math
PPV = \frac{TP}{TP + FP}
```

- [x] **NPV(Negative Predictive Value :陰性的中率)** 

検査で陰性と判断されている中で、実際に陰性の人の割合。


```.math
NPV = \frac{TN}{TN + FN}
```




感度を高くしようとすると特異度が低くなり、特異度を高くしようとすると感度が低くなるトレードオフの関係にあります。目的に合わせて閾値を設定することが望まれます。


##ROC曲線
ROC曲線(Receiver Operating Characteristic curve)は、診断法がどのくらい有用なのか確認するのに使用されます。機械学習であれば、どのくらいモデルが有用であるか確認できます。縦軸に**感度**、横軸に**(1-特異度)**をとります。曲線がグラフ左上の角に近い位置にあるほど感度と特異度が優れており、この値を最適な**カットオフ値**としています。


sklearnを用いると簡単にROC曲線は描くことができます。

```.python
import matplotlib.pyplot as plt
from sklearn.metrics import roc_curve

fpr, tpr, thresholds = roc_curve(t_label, p_score)     
plt.plot(fpr, tpr, marker='o')
plt.xlabel('FPR')
plt.ylabel('TPR')
plt.grid()
plt.savefig('plots/roc_curve.png')
```
*t_label : 正解ラベル, p_score:予測確率

##AUC

AUC(Area Under Curve)とは、ROC曲線の下の面積で0~1をとる。ランダムの時は、0.5になります。値が1に近いほど性能が良いことになります。

AUCは以下のように求めることができます。

```.python
from sklearn.metrics import roc_auc_score
print(roc_auc_score(y_true, y_score))
```

#終わりに
簡単にですがメモ程度でまとめてみました。
今更感がありますが、しばらく触れていないと忘れるので記事として残しておきます。



#参考文献

- [scikit-learnでROC曲線とそのAUCを算出](https://note.nkmk.me/python-sklearn-roc-curve-auc-score/)
- [scikit-learnで混同行列を生成、適合率・再現率・F1値などを算出](https://note.nkmk.me/python-sklearn-confusion-matrix-score/)

- [Chapter 1 Epidemiological Terminology](http://www.med.u-toyama.ac.jp/biostat/Toukeigaku%202nd.pdf)