不器用な老技術者が混同行列について説明するとこうなる

## はじめに
　こんばんは，老技術者でございます。先日，新型コロナウィルスの特集番組を見ていたら抗体検査のところでIgMだのIgGだのって聞き覚えのあるワードが飛び込んできました。記憶を呼び起こしてみたら…はい，やってました。某検査屋さんからの案件で，電気泳動画像からの異常判定のプログラムを書いておりました。IgMだのIgGだのってのはそこに登場する免疫グロブリンのクラス名だったのです。
　人の命にかかわることだから，偽陰性（本当は異常なのに陰性と判定してしまう）ってのはまずいですよね。でも疑わしきはじゃんじゃん陽性にすると，これから話題にする偽陽性（本当は正常なのに陽性と判定してしまう）が増えて検査の信頼性に関わるのでこれまた物言いがつきます。これを複数のパラメータのそれぞれの閾値を動かすことで良い案配にチューニングするのです。その微妙な匙加減を自動化するのが老技術者の腕の見せ所なのでした。
　ところが，どう匙加減を調整してもなかなか陽性判定検体中の偽陽性の割合が減らないことがあります。それが，病理検査でありがちな「不均衡データ」（例えば，感染検体数が非感染検体数に比べて100分の1とか）の場合です。
　そこで今宵のお話は，**閾値の選び方によって，病理検査結果がこうも変わるんだ！**ということを数値実験で体感するとともに**「不均衡データ」の扱いの難しさ**についてもわかった感じになっていただこうと思います。なお，以下では話を分かりやすくするために，感染症の抗体検査を例に説明していきます。

## 仮定
　次の単純な仮定を置いて考えることにします。

**1.　陰性/陽性判定のための閾値を設定するパラメータは1つだけである
2.　そのパラメータに対して，非感染（陰性）検体，感染（陽性）検体それぞれが正規分布している**

この2つの仮定のもとに，まずは個体数，標準偏差が全く同じで平均だけが違う2つの群のデータを生成します（**図1**）。

<img width="600pix" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202911/e2708f85-2bd0-11ac-2329-bd4a0affb34b.png">



このヒストグラムで，左の赤い山が実際の非感染検体，右の青い山が実際の感染検体です。

## 用語の整理
　はじめに**図2**を見ながら今回使用する用語の整理をしておきます。まず，パラメータ値の閾値（カットオフ値，Threshold）を決めます。青い線で示したのが閾値とするとその左側が陰性判定，右側が陽性判定となります。次に「実際に**非感染検体**か**感染検体**か」と「判定が**陰性判定**か**陽性判定**か」の組合せで次の4つのカテゴリーを定義します。

<table border="1">
    <tr>
      <th colspan="3">分類名</th>
      <th>覚え方</th>
      <th>定義</th>
    </tr>
    <tr>
      <td><b>TN</b></td>
      <td>True Negative </td>
      <td><b>真陰性</b></td>
      <td>正しく陰性</td>
　　　<td>非感染検体を正しく陰性と判定 </td>
    </tr>
    <tr>
      <td><b>FP</b></td>
      <td>False Positive </td>
      <td><b>偽陽性</b></td>
      <td>間違えて陽性</td>
　　　<td>非感染検体を間違えて陽性と判定 </td>
    </tr>
    <tr>
      <td><b>FN</b></td>
      <td>False Negative</td>
      <td><b>偽陰性</b></td>
      <td>間違えて陰性</td>
　　　<td>感染検体を間違えて陰性と判定</td>
    </tr>
    <tr>
      <td><b>TP</b></td>
      <td>True Positive</td>
      <td><b>真陽性</b></td>
      <td>正しく陽性</td>
　　　<td>感染検体を正しく陽性と判定</td>
    </tr>
</table>


Tを「正しく」，Fを「間違えて」，Pを「陽性」，Nを「陰性」と読み替えると覚えやすいです。
いま仮に閾値（Threshold，青線）を100として，その左側が陰性判定（Negative），右側が陽性判定（Positive）であるとします。先ほどのヒストグラムに色を付けて，TN，FP，FN，TPの定義を確認しましょう。

<img width="600pix" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202911/84762a2a-c4bc-41c0-57b1-910397d63774.png">


非感染検体だけを見てみると，**図3**のようになります。
　　青線の左側は「正しく陰性判定」つまり**真陰性（TN）**，
　　青線の右側は「間違えて陽性判定」つまり**偽陽性（FP）**
となります。

<img width="600pix" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202911/f5675a32-d176-b0c2-f148-9638de366e21.png">




感染検体だけを見てみると，**図4**のようになります。
　　青線の左側は「間違えて陰性判定」つまり**偽陰性（FN）**，
　　青線の右側は「正しく陽性判定」つまり**真陽性（TP）**
となります。

<img width="600pix" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202911/a0909b18-f735-f112-ae06-a148486f4d9d.png">



## 分類の評価
閾値を設定して，検体を陰性・陽性に分類する際，この分類の評価はどのようにしたらよいでしょうか？
まずは，先ほど紹介したTN，FP，FN，TPそれぞれの個体数を数えて表にします。この表のことを**混同行列（confusion matrix）**といいます。

<table border="2" >
    <tr>
      <th colspan="2" rowspan='2'> </th>
      <th colspan="2" align='center'>予測</th>      
    </tr>
    <tr>
      <th>陰性</th>
      <th colspan="2">陽性</th>      
    </tr>
    <tr>
      <th rowspan='2'>検体</th>
      <th> 非感染</th>
      <td>TN</td>
      <td>FP</td>
    </tr> 
    <tr>
      <th>感染</th>
      <td>FN</td>
      <td>TP</td>
    </tr> 
</table>

閾値を決めるうえで注目するのは次の4つの指標です。
(1) **正解率（accuracy）**
正解率は**全個体の中で正しく予測できたもの**の割合で
$$
正解率=\frac{TN + TP}{FN + FP + TN + TP}
$$
と計算します。色分けしてこの定義式と混同行列との関係を見ると次のようになります。

<img width="480pix" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202911/205a869c-be0c-5e99-3419-2c03bcbce6c9.png">

(2) **適合率（precision）**
適合率は**陽性と判定した中で正しく予測できたもの**の割合で
$$
適合率=\frac{TP}{FP + TP}
$$
と計算します。色分けしてこの定義式と混同行列との関係を見ると次のようになります。

<img width="480pix" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202911/6c31aaae-684e-5746-0cae-57a64df27c01.png">



(3) **真陽性率（true positive rate，TPR）**
再現率は**感染検体の中で正しく陽性と予測できたもの**の割合です。
**再現率（recall**），感度（sensitivity）ともいい，
$$
真陽性率=\frac{TP}{FN + TP}
$$
と計算します。色分けしてこの定義式と混同行列との関係を見ると次のようになります。

<img width="480pix" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202911/ffbbc177-1a40-e803-9306-47e55f7ddad9.png">

(4) **偽陽性率（false positive rate，FPR）**
偽陽性率は非感染検体の中で誤って陽性と予測してしまったものの割合で
$$
偽陽性率=\frac{FP}{TN + FP}
$$
と計算します。色分けしてこの定義式と混同行列との関係を見ると次のようになります。

<img width="480pix" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202911/3c08ed0c-7718-e9e6-2000-070fa65978ad.png">

例えば**閾値が100の場合の混同行列**は下表のようになります。

<table border="2" >
    <tr>
      <th colspan="2" rowspan='2'> </th>
      <th align=center colspan="2" >予測</th>      
    </tr>
    <tr>
      <th>陰性</th>
      <th colspan="2">陽性</th>      
    </tr>
    <tr>
      <th rowspan='3'>検体</th>
      <th> 非感染</th>
      <td>84006</td>
      <td>15994</td>
    </tr> 
    <tr>
      <th>感染</th>
      <td>2321</td>
      <td>97679</td>
    </tr> 
</table>
ヒストグラムは

<img width="600pix" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202911/d81e5110-9d2c-e7d3-c906-ba38f62f6181.png">

<img width="600pix" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202911/daa674a3-7b5d-faa8-37a6-c7b06764b613.png">


**閾値が130の場合の混同行列**は下表のようになります。

<table border="2" >
    <tr align=center>
      <th colspan="2" rowspan='2'> </th>
      <th colspan="2" align=center>予測</th>      
    </tr>
    <tr>
      <th>陰性</th>
      <th colspan="2">陽性</th>      
    </tr>
    <tr>
      <th rowspan='2'>検体</th>
      <th> 非感染</th>
      <td>99388</td>
      <td>612</td>
    </tr> 
    <tr>
      <th>感染</th>
      <td>30766</td>
      <td>69234</td>
    </tr> 
</table>
ヒストグラムは

<img width="600pix" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202911/3630f244-ff58-2ea5-4e0d-843decf7b9d0.png">

<img width="600pix" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202911/5381a3f1-19ec-d64f-20d8-916bd884240b.png">

つまり閾値を100から130にすると

<table border="2" >
    <tr>
      <th colspan="2" rowspan='2'> </th>
      <th colspan="2" align='center'>予測</th>      
    </tr>
    <tr>
      <th>陰性</th>
      <th colspan="2">陽性</th>      
    </tr>
    <tr>
      <th rowspan='2'>検体</th>
      <th> 非感染</th>
      <td>TN 増</td>
      <td>FP 減</td>
    </tr> 
    <tr>
      <th>感染</th>
      <td>FN 増</td>
      <td>TP 減</td>
    </tr> 
</table>

となることがわかります。上記の4つの評価指標を計算してみると下表のようになります。

<table border="2" >
    <tr>
      <th colspan="1" rowspan='2'>評価指標 </th>
      <th colspan="2" align='center'>閾値</th>      
    </tr>
    <tr>
      <th>100</th>
      <th colspan="2">130</th>      
    </tr>
    <tr>
      <th> $$
正解率=\frac{TN + TP}{FN + FP + TN + TP}
$$</th>
      <td>0.90842</td>
      <td>0.84311</td>
    </tr> 
    <tr>
      <th>$$
適合率=\frac{TP}{FP + TP}
$$</th>
      <td>0.85929</td>
      <td>0.99123</td>
    </tr> 
    <tr>
      <th>$$
真陽性率=\frac{TP}{FN + TP}=再現率
$$</th>
      <td>0.97679</td>
      <td>0.69234</td>
    </tr> 
    <tr>
      <th>$$
偽陽性率=\frac{FP}{TN + FP}
$$</th>
      <td>0.15994</td>
      <td>0.00612</td>
    </tr> 
</table>


閾値を連続的に変えていったときにこれらの評価指標がどう変化するかを図示すると**図9**のようになります。

<img width="500pix" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202911/4ce76bcf-54a0-2958-4ac4-40328fbbb79e.png">

閾値が100の場合と130の場合を比較してみると，病理検査で重要な真陽性率は閾値100の方が高く，それとトレードオフ関係になる適合率も0.85付近とそこそこ高くなっています。一方，閾値130では適合率はほぼ1になっていますが真陽性率が0.7未満ということで感染検体の30%以上を陰性と判定して見逃してしまうことになります。
そこで見逃しが許されない病理検査でしたら閾値100かさらにその下の閾値を使うのが良いということになります。


## 不均衡データの場合
　上の数値実験は感染検体と非感染検体が同数というケースでした。しかし，実際の病理検査ではたいていの場合，非感染検体に比べ感染検体が著しく少ない，いわゆる不均衡データとなります。この場合，何が違ってくるでしょうか。いま10万:1万の不均衡データを生成してみました。

<img width="600pix" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202911/bd9214ae-6914-64d3-7830-a6f7034cabd7.png">


閾値が100の場合の混同行列は下表のようになります。

<table border="2" >
    <tr>
      <th colspan="2" rowspan='2'> </th>
      <th align=center colspan="2" >予測</th>      
    </tr>
    <tr>
      <th>陰性</th>
      <th colspan="2">陽性</th>      
    </tr>
    <tr>
      <th rowspan='3'>検体</th>
      <th> 非感染</th>
      <td>84006</td>
      <td>15994</td>
    </tr> 
    <tr>
      <th>感染</th>
      <td>657</td>
      <td>9343</td>
    </tr> 
</table>
ヒストグラムは

<img width="600pix" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202911/d8e84b24-b13d-603d-fd47-504542da9c0f.png">


となります。
非感染検体だけ取り出してみると

<img width="600pix" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202911/b0ea9b4e-1b19-7dab-67c5-b11bf4552260.png">

これは均衡データの場合と同じですので図５と全く同じになっています。
次に感染検体だけ取り出してみましょう。

<img width="600pix" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202911/1d963346-8002-e463-6847-89b3d00c9e56.png">


となり，病理検査で問題となる偽陰性（FN）は小さく抑えられています。
ところが，検査の結果，陽性と判定された検体だけ見てみると，
<img width="600pix" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202911/fb4f7357-2511-a3bc-33c4-4522cce4bc9a.png">

となります。適合率は陽性と判定した中で正しく予測できたものの割合で，閾値100では，
$$
適合率=\frac{TP}{FP + TP}=\frac{9343}{15994 + 9343}=0.3687
$$
となります。**陽性と判定した検体中の偽陽性の割合**（つまり1-適合率）が6割以上に達するというのは由々しき問題です。
閾値を上にずらしていけばこの偽陽性の割合は減っていきますが，代わりに本当は感染検体なのに間違って陰性と判定された検体（偽陰性）が増えてしまいます（**図15**）。これはもっと由々しい事態です。

<img width="480pix" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202911/9feac913-ecc6-3d55-2be4-029d23783ccc.png">



つまり，**不均衡データでは偽陰性検体数を抑えようとすると必然的に偽陽性検体数が著しく多くなってしまう**，という一例が上の数値実験から示せたことになります。