医療とテクノロジーの交差点にて【第8話】統計学は最強の学問であるのか?
どうも、トア・ルドクターです!
今回のテーマは、統計学を含めた解析手法の意義についてです。
「統計学は最強の学問である」という本が数年前に流行りましたが、ここ数年でデータサイエンス関連の本・pythonを用いた解析手法の本などが急増しています。理由としては、2012年にジェフリーヒントン教授が率いるグループが画像認識の制度で人間を超えたとか、2015年にDeepMind社(Googleの系列企業)の開発したAlphaGoが囲碁のプロ棋士(韓国のリ・セドル)を倒したとか、昨今のディープラーニング技術の台頭が背景にあります。華やかなニュースに胸が踊る一方で、どういう解析手法(ディープラーニング含めて)が優れているとか、新しいアルゴリズムが発明されたとか、といった点ばかりにフォーカスがいく世の風潮に少し違和感を覚えています。
データサイエンス全盛期の御時世に、pythonなどのプログラミング言語を学んだり、ディープラーニングを含めた解析手法を学んだりすることは有意義だと断言できます。しかし、いくら優れた解析手法・アルゴリズムを学んだとしても不十分で、データサイエンスというのはデータありきの学問だということを再認識する必要があります。データの質と量ともに大切で、胡散臭い悪質なデータを大量に学習するのは荒唐無稽ですし、一方で信頼に足りうるデータだろうと数が少なければ適切な学習結果は得られません。要するに、一流のシェフが一流の料理器具を用いても、そもそも食材がなければ無力なわけです。
企業のアプリ開発であれば(ほとんどの場合)実用性が全てなので、動作さえすればデータや解析手法に拘りすぎる必要がありませんが、学術的な論文・学会発表となると元データ・解析手法を赤裸々に開示する必要があります。ここに学問としてのデータサイエンスの難しさがあります。
解析の実例
さて、私が実際に解析した実例をみていきましょう。概要としては「胸腺腫37症例を5グループに分けて、各グループごとの造影CT値の平均に差があるか」を検討しました。使った知識としては、等分散の検定→母平均の差の検定→ボンフェローニ補正...といった単純なものだけです。これらの検定はあくまで2群間比較なので、5群の比較をする上で5C2の10通りの組み合わせについて用いています。その際にボンフェローニ補正というものが必要になります。詳細は後述します。
以下は実際に用いたpython3コードです。
F検定(等分散の検定)
import random, math
import numpy as np
import matplotlib.pyplot as plt
import statistics as st
from scipy.stats import t,f
# 標準入力
x = list(map(int,input().split()))
y = list(map(int,input().split()))
# 不偏推定量たち
m,n = len(x),len(y)
mx,my = st.mean(x),st.mean(y) # np.average()
vx,vy = st.variance(x),st.variance(y) # np.var
sx,sy = st.stdev(x),st.stdev(y) # np.std()
# F検定
ff = vx/vy
low = f.ppf(0.025,m-1,n-1)
high = f.ppf(0.975,m-1,n-1)
reject = ff<low or high<ff
# 出力
print(vx,vy)
print(ff)
if reject: print("分散は等しくない")
else: print("分散は等しい")
T検定(母平均の差の検定)
import random, math
import numpy as np
import matplotlib.pyplot as plt
import statistics as st
from scipy.stats import t
# 標準入力
x = list(map(int,input().split()))
y = list(map(int,input().split()))
# 不偏推定量たち
m,n = len(x),len(y)
mx,my = st.mean(x),st.mean(y) # np.average()
vx,vy = st.variance(x),st.variance(y) # np.var
sx,sy = st.stdev(x),st.stdev(y) # np.std()
# 標本統計量T:母分散が等しい
v = ((m-1)*vx+(n-1)*vy)/(m+n-2)
t1 = (mx-my)/math.sqrt(v*(1/m + 1/n))
# 標本統計量T:母分散が等しいか不明
k = (vx/m)**2/(m-1) + (vy/n)**2/(n-1)
t2 = (mx-my) / math.sqrt(k)
# P値:母分散が等しい
p1 = t.cdf(-abs(t1), m+n-2)*2 # cdfはppfの逆関数
# P値:母分散が等しいか不明
nu = ((vx/m+vy/n)**2) / k
p2 = t.cdf(-abs(t2), nu)*2
# 等分散か
q = input("等分散? y/n")
if q == "y":
tt,p = t1,p1
else:
tt,p = t2,p2
# 棄却域
low = t.ppf(0.025, m+n-2) # マイナスの端っこ
high = t.ppf(0.975, m+n-2)
reject = (tt < low) or (high < tt)
# 出力
print(mx,my)
if reject: print("有意差あり")
else: print("有意差なし")
print("p値、標本統計量T、下限、上限")
print(round(p,4),"",round(tt,4),"",low,"",high)
胸腺腫瘍の分類にWHO分類(病理所見の分類)があります。
以下の5グループ(A / B / AB / B1 / B2 / B3)ごとに造影CTのCT値(増強度)を計測しました。
この5グループごとにCT値の平均を求めます。方法の詳細は以下。
CT値の平均をグループごとに比較した結果が以下の通り。解析に用いた生データは個人特定には微塵も関係しない数字のみの配列ですが、念のため開示しません。
本来は2群間比較に用いるt検定を5群間の比較に用いており、ボンフェローニ補正を施しております。
この結果の解釈は以下の通り。
正直うさんくさい結果。そもそもの数が少ないとか、計測法が怪しいとか(ROI選択は手動だし)、改善点は枚挙にいとまがありません。
このように解析手法というより、そもそものデータの信頼度だったり、データの数がむしろ問題になります。解析手法よりもデータの集積方法に改善の余地があるわけです。優れたアプリ開発・研究するには、優れたアルゴリズムよりも優れたデータなのです。
最後に、個々の統計手法について簡単にまとめておきます。
等分散の検定
●
T検定(母平均の差の検定)
●
ボンフェローニ補正
●
内容は以上です。
それではまたいつか!
【著者プロフィール】
都内で医師として研鑽する傍ら、独学でプログラミングを学ぶ26歳。趣味は『ギター / バイオリン / 美術鑑賞 / youtube鑑賞 / 創作料理 / 囲碁 / チェス / 折り紙 / スノボ / サーフィン / ドライブ』など枚挙にいとまがない。CIAの格闘武術クラブマガを始める。得意料理はバナナシチュー。ビールと牡蠣は生派だが生セックスは断固せず、経験人数の常用対数は2未満と清純を極める。略歴としては高2で数学全国1位(駿台)、文系で官僚をめざすも、ドラマ『コードブルー』の影響から気づいたら医師に。ディープラーニングG検定、統計検定2級、知的財産検定3級など取得。TOEICは次回900目指す予定(仮)。
【記事アーカイブ】
【第1話】医者なのにプログラミングを勉強してみた話
【第2話】pythonプログラミングの小技(1)ラムダ
【第3話】プログラミング初心者が学ぶべき3つのポイント
【第4話】競技プログラミングのススメ
【第5話】競技プログラミング物語(1)バイトリーダーの苦悩
【第6話】プログラミングで自作する実用アプリ(1)NEVER-NOTE
【第7話】プログラミングで解析したDNA鑑定の精度
【第8話】統計学は最強の学問であるのか?
【第9話】プログラミングすれば人類最高IQに対抗できる説
この記事が気に入ったらサポートをしてみませんか?