30日Python #26 見逃しと、空振りは、違う(感度と特異度)
「読むデータ」は、臨床医・医学研究者のための、Pythonと機械学習の連載。プログラミングの技術を身につけることから始め、自分のデータを「読み解く」力を鍛える。今回の#26では、混同行列から感度と特異度を読み取る。「見逃さない力」と「空振りしない力」を分けて測り、何を陽性とみなすかで数字がどう変わるかを学ぶ。所要時間は5分。読むのに3分、手を動かすのに2分。
二つの実力を、分けて測る
前回、混同行列で間違いを4つに分けた。悪性の見逃しと、良性の取り違え、性質の違う二つの間違いがあった。
ならば、モデルの「良さ」も、二つに分けて測るべきだ。一つは、悪性をどれだけ見逃さずに捕まえられるか。もう一つは、良性をどれだけ余計に疑わずに済むか。前者を感度、後者を特異度と呼ぶ。臨床検査でおなじみの、あの二つだ。
機械学習のモデルも、検査の一種として、この二つの物差しで測れる。今日はそれを、自分のモデルで計算する。
要点
感度は「実際に悪性の人のうち、悪性と当てられた割合」。見逃さない力。
特異度は「実際に良性の人のうち、良性と当てられた割合」。空振りしない力。
どちらを「陽性」と呼ぶかで、感度と特異度は入れ替わる。何を見つけたいのかを先に決める。
1. 何を「陽性」とするかを、決める
感度と特異度を計算する前に、必ず決めることがある。何を「陽性(見つけたい対象)」とするか、だ。
このデータでは0が悪性、1が良性だった。だが、私たちが見つけたいのは悪性のほうだ。だから今回は、悪性を陽性として考える。「悪性という異常を、検査(モデル)で見つけ出す」という構図だ。これを決めておかないと、感度と特異度の意味が定まらない。
2. 感度と特異度を、計算する
前回の混同行列を思い出そう。これは前回算出させた混同行列の出力である。
array([[ 59, 4],
[ 5, 103]])実際に悪性だった人は、上の行の 59 + 4 = 63人。このうち、正しく悪性と当てられたのは59人。
感度(悪性を見つける力)= 59 / 63 = 0.937
実際に良性だった人は、下の行の 5 + 103 = 108人。このうち、正しく良性と当てられたのは103人。
特異度(良性を見抜く力)= 103 / 108 = 0.954
感度93.7%、特異度95.4%。このモデルは、悪性の患者の約94%を捕まえ、良性の患者の約95%を正しく見送る。
前回の「正解率0.947」という一つの数字が、ここで「見逃さない力」と「空振りしない力」の二つに分かれた。
3. 「陽性」を入れ替えると、数字も入れ替わる
ここが、最も誤読されやすいところだ。感度・特異度は、何を陽性とみなすかで、まるごと入れ替わる。
もし「良性を陽性」として計算したら、いま感度と呼んだ数字は特異度になり、特異度は感度になる。値そのものが変わるのではなく、どちらを感度と呼ぶかが反転するのだ。
だから、感度95%と書かれた数字を見たとき、まず問うべきは「何を陽性としているか」だ。それが悪性なのか良性なのか、検査で見つけたい対象が何なのかを確かめずに数字だけ受け取ると、「見逃さない力」と「空振りしない力」を取り違える。
論文を読むときも、自分のモデルを語るときも、まず陽性の定義を確かめる。数字は、その定義の上にしか意味を持たない。
今日の実習(2分)
新しいセルで、上から順にやってみよう。
(前回の混同行列がある状態を想定)
混同行列の数字から、感度を手で計算する。59 ÷ 63 を実行し、約0.937になることを確かめる。
特異度も計算する。103 ÷ 108 を実行し、約0.954になることを確かめる。
もし「良性を陽性」とみなしたら、この二つの数字の役割がどう入れ替わるかを考えてみる。
電卓のように 59/63 とセルに打てば、Pythonが計算してくれる。
今日のまとめ
感度は「悪性を見逃さない力」、特異度は「良性を空振りしない力」。
正解率という一つの数字ではなく、この二つに分けて測る。
そして、どちらを陽性とみなすかで、感度と特異度は入れ替わる。数字を読むとき、まず「何を陽性としているか」を確かめる。これを怠ると、見逃さない力と空振りしない力を、正反対に読んでしまう。
次回、第27回「一本の線で、性能を測る」
感度と特異度は、判断の基準を動かすと連動して変わる。その関係を一本の曲線(ROC曲線)に描き、曲線の下の面積(AUC)で性能をまとめて測る方法を学ぶ。
