【超初心者向け】ROC曲線とAUCについてわかりやすく解説
機械学習で分類モデルを作成した際、モデルの精度をどのように評価すべきかは非常に重要です。
モデルを評価するための評価指標として、分類モデルの場合は正解率 (Accuracy) や再現率 (Recall) 等、様々な評価指標があります。
今回は、分類問題でよく使用される評価指標であるROC曲線とAUCについてわかりやすく解説します。
真陽性率 (TPR) と偽陽性率 (FPR)
ROC曲線を学ぶ前に基礎知識として、真陽性率 (TPR : True Positive Rate)と偽陽性率 (FPR : False Positive Rate)について学ぶ必要があります。
- TPR:全ての陽性のうち、実際に陽性であるものを正しく陽性と判定できた割合
- FPR:全ての陰性のうち、実際に陰性であるものを誤って陽性と判定した割合
定義は上記の通りですが、より具体的な例を見ながら分かりやすく説明していきたいと思います。
今回は、乳癌の画像分類の具体例を用いて、TPR と FPR について理解を深めていきましょう。
入力した画像が、正常か乳癌かを分類するモデルを作成したとします。
モデルによる推論のイメージ
このモデルを使用して1000枚のマンモグラフィー画像を正常、乳癌に分類する作業を行いました。
混同行列
これから、TPRとFPRを理解するにあたって、混同行列(Confusion Matrix)について理解する必要があります。
混同行列(Confusion Matrix)とは、分類問題で出力されたクラス分類の結果をまとめたマトリックスのことで、主に2値分類機械学習モデルの性能を測る指標として使われます。(2行×2列のマトリックス)
ここで、「陽性(Positive)」と表現しましたが、これは「状態あり」を意味し、機械学習では「正例」と表記される場合があります。
また、「陰性(Negative)」は「状態なし」を意味し、「負例」と表記される場合があります。
医療においては異常(癌などの疾患)を陽性(Positive)、正常を陰性(Negative)とする事が多い。
図2を見ると分かるように、混同行列の各項目の意味は以下の通りである。
- TP(True Positive:真陽性)=正解値が陽性(Positive)に対して、正しく予測値が陽性(Positive)だと予測
- FN(False Negative:偽陰性)=正解値が陽性(Positive)に対して、誤って予測値が陰性(Negative)だと予測
- FP(False Positive:偽陽性)=正解値が陰性(Negative)に対して、誤って予測値が陽性(Positive)だと予測
- TN(True Negative:真陰性)=正解値が陰性(Negative)に対して、正しく予測値が陰性(Negative)だと予測
図3に具体例を示します。
陽性のうち、実際に陽性だったものを正しく陽性と判定できた割合(73%)がTPR、そして全陰性のうち、実際は陰性だったが間違えて陽性と判定した割合(30%)がFPRになります。計算すると以下になります。
改めて、定義を載せておきます。
- TPR:全ての陽性のうち、実際に陽性であるものを正しく陽性と判定できた割合
- FPR:全ての陰性のうち、実際に陰性であるものを誤って陽性と判定した割合
最初よりも定義の意味が理解できたのではないでしょうか。
それではこのTPR とFPRを押さえた上で、ROC曲線とAUCを理解していきましょう。
ROC曲線とは
ROC曲線とは以下の図のような曲線です。
これから、ROC曲線の成り立ちや仕組みを解説していきたいと思います。
縦軸はTPR、横軸はFPRを表しており、分類する際の閾値を変更した際の TPR、FPRの値をプロットしています。
こちらも、具体例を使用してお伝えします。
ROC 曲線の理解を深めるため今回もマンモグラフィ画像の乳癌分類を例に使用します。
分類を行った結果、以下の表のようなデータが得られました。(陽性と予測した予測確率を出力)
この結果を、ROC曲線で評価するための考え方を解説していきます。
ROC曲線を考える時は、分布と閾値が重要なポイントになっています。
- 分類する際の閾値を変更した際のTPR、FPRの値をプロットしたもの
オレンジ:陽性、青:陰性の分布とします。
予測確率が出力され、閾値によってどこから陽性でどこから陰性かを分けていきます。
次の図 のように「陽性/陰性」がどこかの値(Threshold:閾値)で綺麗に区切れるのであれば最も理想です。
その場合は、感度も特異度も100%の完璧な判定ができます。
しかし、そんなにうまくいくことはほとんどありません。
そのの中で「多少良いとされる・許容される」判定とは、「陽性のものを分類したときの出力の分布と、陰性のものを分類したときの出力の分布を較べると差がある」ものになります。
つまり、ある閾値を決めて、それより出力が大きいものは、全体と較べて「陽性」のものの割合が多くなり、出力が小さいものは「陽性」のものの割合が少なくなるようにグループに分けられるものということです。(下図を参照)
許容できるくらいの多少良い判定の場合、たとえば出力値の分布は上図(図8,9)のようになります。
「陽性/陰性」の分布が重なる部分がどうしても出てくることになります。
本来は、陰性であるものが陽性と予測されたものを「偽陽性」、本来、陽性であるものが陰性と予測されたものを「偽陰性」といいます。
それぞれの言葉の意味については下図を参照してください。
最も悪いROC曲線、いまいちな判定の場合は、次の図のように同じくらい分布が重なってしまうような場合です。
どこの閾値で切っても、陽性/陰性をうまく分けることが出来ません。
判定の良し悪しを見るために「閾値を変えたときにどれくらい切り分けられかたが変わるか」をグラフに表したのが、ROC曲線です。
改めて、定義を載せておきます。
- 分類する際の閾値を変更した際のTPR、FPRの値をプロットしたもの
最初よりも定義の意味が理解できたのではないでしょうか。
それでは続いて、AUCを理解していきましょう。
ROC曲線が理解できていれば、簡単です。
AUCとは
AUCとは以下の図のようなROC曲線の曲線下面積のことです。
AUCは、Area Under the Curve の略であり、ROC曲線の下部分の面積のことです。
最も良い理想のAUCはAUC=1.0、最も悪いAUCはAUC=0.5になります。
つまり、陽性と陰性をきれいに分類できていればAUCは1.0に近づき、ランダムな分類をしていると AUCは0.5に近づくことがわかります。
このことから AUCが1に近いほど、優れた分類モデルであるといえます。
Pythonによる評価指標の実装
それでは、これから今まで学んできたROC曲線とAUCをPythonで実装してみようと思います。
今回は、skleanのライブラリから「breast cancer」のデータセットを使用します。
▼ データセットの内容はこちら
全データ数 | 569 サンプル |
どんな機械学習ができるか | 分類問題(良性か悪性か) |
予測する対象 | 説明 | |
---|---|---|
malignant | 悪性 | データ内では「 0 」で表されます |
benign | 良性 | データ内では「 1 」で表されます |
まずは必要なライブラリをインポートします。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn import metrics
from sklearn.metrics import accuracy_score
from sklearn.metrics import recall_score
from sklearn.metrics import precision_score
from sklearn.metrics import confusion_matrix
import seaborn as sns
続いて、データセットを読み込んで、データフレームに格納します。
dataset = load_breast_cancer()
df = pd.DataFrame(dataset.data, columns=dataset.feature_names)
df.head()
データセットは上図のようになっています。
df['target'] = dataset.target_names[dataset.target]
予測したい値をtargetとします。
そして、説明変数をXに、目的変数をYに格納します。
X = dataset.data
Y = dataset.target
続いて、train_test_splitを使用して、学習用70%、テスト用30%にデータを分けます。
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.3, random_state=0)
次に、今回はランダムフォレストを用いて、学習を行います。
n_estimators(木の数)
min_samples_split(木ノードにおいてそれ以上分割を行うための最少サンプル数)
それぞれのパラメータは上記を意味しています。
model = RandomForestClassifier(max_depth=3, n_estimators = 100, random_state = 0)
forest = model.fit(X_train, y_train)
y_pred = forest.predict(X_test)
学習した結果を用いてテスト用のデータで、性能評価を行います。
acc = accuracy_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
print("Accuracy:",acc)
print("Recall:",recall)
print("Precision:",precision)
cm = confusion_matrix(y_test, y_pred)
tn, fp, fn, tp = cm.ravel()
print("tn, fp, fn, tp =" ,tn, fp, fn, tp)
Recall: 0.9629629629629629
Precision: 0.9629629629629629
tn, fp, fn, tp = 59 4 4 104
上記コードで混同行列を出力できていますが、より見やすくするために、かっこよく可視化してみたいと思います。
sns.heatmap(cm, square=True,annot=True, cmap='Blues', fmt='g')
plt.xlabel("Pred Label")
plt.ylabel("True Label")
plt.show()
かなりかっこよく混同行列を可視化することが出来ました。
最後に、ROC曲線とAUCを実装したいと思います。
fpr, tpr, threshold = metrics.roc_curve(y_test, y_pred)
auc = metrics.auc(fpr, tpr)
plt.plot(fpr, tpr, label='ROC curve (area = %.2f)'%auc)
plt.legend()
plt.title('ROC curve')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
きれいにROC曲線を描画できましたね。
AUCも一緒に可視化することが出来ました。
以上で、Pythonによる実装は完了です。
まとめ
今回は、分類問題でよく使用される評価指標であるROC曲線とAUCについてわかりやすく解説しました。
理論からPythonによる実装まで学べる内容にしました。
ぜひ、参考にしていただけると嬉しいです。
最後に、今回学んだ定義をまとめておきます。
- TPR:全ての陽性のうち、実際に陽性であるものを正しく陽性と判定できた割合
- FPR:全ての陰性のうち、実際は陰性であるものを誤って陽性と判定した割合
- ROC:分類する際の閾値を変更した際のTPR、FPR の値をプロットしたもの
- AUC:Area Under the Curve の略であり、ROC曲線の下部分の面積のこと
コメント