新薬を14人に投与したら11人が治り、偽薬を飲んだ14人では4人しか治らなかった——この差は「薬が効いた証拠」と言ってよいのでしょうか、それとも14人ずつという小さなサンプルでたまたま起きた偶然なのでしょうか。あるいは、2つの画像分類器を同じテスト画像1000枚で比べたら、片方が0.5%だけ精度が高かった。この0.5%は実力差なのか、誤差なのか。
こうした「2×2の表に集計したデータから、本当に差があるかを判定する」問題は、医療・マーケティング・機械学習のあらゆる現場に現れます。定番の道具はカイ二乗検定ですが、これは標本が小さいと答えがずれてしまう近似手法です。そこで登場するのが、フィッシャーの正確検定(Fisher’s exact test)——超幾何分布を使って、近似なしの厳密なp値を計算する手法です。さらに、「同じ患者の治療前と後」「同じテストデータでの2分類器」のように対応のある(ペアになった)データでは、マクネマー検定という別の道具が必要になります。
この記事を読むと、次の場面で正しい検定を選び、自分で計算できるようになります。
- 医療: 治療効果の有無を小標本で判定する(フィッシャー)/同一患者の前後比較(マクネマー)
- A/Bテスト: 2つのデザインのコンバージョン率に差があるか
- 機械学習: 2つの分類器の精度差が統計的に有意か(マクネマー)
本記事の内容
- 2×2分割表の構造と、周辺度数という重要概念
- カイ二乗検定が小標本(期待度数 < 5)で崩れる理由
- フィッシャー正確検定の核心——超幾何分布による厳密p値の導出
- 効果量としてのオッズ比と相対リスクの違い
- 対応ありデータのマクネマー検定と、コクランのQ検定(3条件以上)
- 検定の選び方(独立 vs 対応、標本サイズ)のフローチャート
scipy.statsを使ったPython実装と、分類器比較への応用
前提知識
この記事を読む前に、以下の記事を読んでおくと理解が深まります。
2×2分割表とは
まず、議論の舞台となる分割表(contingency table) を整理しましょう。分割表は、2つのカテゴリ変数の組み合わせごとに、該当する個体の数(度数)を並べた表です。最も基本的なのが、行2つ・列2つの 2×2分割表 です。
たとえば「治療群か対照群か(行)」と「治った/治らなかった(列)」を交差させると、4つのセルにそれぞれ人数が入ります。このセルを左上から $a, b, c, d$ と呼ぶことにします。

図のように、各セルの値を行方向・列方向に足したものを 周辺度数(marginal totals) と呼びます。$a+b$ は群Aの総数、$a+c$ は成功した総数、そして $n = a+b+c+d$ が全標本数です。
$$ \begin{array}{c|cc|c} & \text{成功} & \text{失敗} & \text{行計} \\ \hline \text{群A} & a & b & a+b \\ \text{群B} & c & d & c+d \\ \hline \text{列計} & a+c & b+d & n \end{array} $$
この表に対して私たちが問いたいのは、「群(行)と結果(列)は独立か、それとも関連があるか」です。独立なら「群を変えても成功率は変わらない=治療に効果はない」、関連があるなら「群によって成功率が違う=効果がある」と解釈できます。これがすべての分割表検定の共通の問いです。
周辺度数という言葉を強調したのには理由があります。後で見るフィッシャー検定では、この周辺度数を「固定された前提条件」として扱うことが鍵になります。まずは標準的な道具であるカイ二乗検定から始め、それがどこで限界を迎えるかを見ていきましょう。
カイ二乗検定の限界
期待度数とカイ二乗統計量
カイ二乗検定の発想はシンプルです。「もし群と結果が完全に独立なら、各セルにはどれだけの度数が入るはずか」を計算し(期待度数)、実際の観測度数とのズレを測ります。独立なら、セル $(i,j)$ の期待度数は周辺度数の積を全体で割った値です。
$$ E_{ij} = \frac{(\text{行}i\text{の合計}) \times (\text{列}j\text{の合計})}{n} $$
観測度数 $O_{ij}$ と期待度数 $E_{ij}$ のズレを二乗して相対化し、全セルで足し合わせたものがカイ二乗統計量です。
$$ \chi^2 = \sum_{i,j} \frac{(O_{ij} – E_{ij})^2}{E_{ij}} $$
帰無仮説(独立)が正しければ、この統計量は自由度1の $\chi^2$ 分布に近似的に従います。この「近似的に」が今回の主役です。
なぜ近似なのか、どこで崩れるか
カイ二乗統計量が $\chi^2$ 分布に従うのは、各セルの度数が十分大きく、正規分布で近似できるときに限ります。度数は本来とびとびの整数値(離散)なのに、連続な $\chi^2$ 分布で近似しているわけです。標本が大きければこの近似は精度が高いのですが、セルの期待度数が小さい(おおむね5未満)と、近似がずれてp値が信頼できなくなります。経験則として「すべてのセルで期待度数 ≥ 5」が目安とされます。
実際にどれだけずれるか、見てみましょう。周辺度数を固定し、セル $a$ の値だけを動かしながら、カイ二乗近似のp値とフィッシャー正確検定のp値を比べた図が次です。

左の図から、総数 $n=16$ という小標本では、カイ二乗近似(青)と正確p値(赤)が無視できないほど離れていることが読み取れます。特に有意水準0.05の付近で両者がまたぎ違っており、近似に頼ると「有意/非有意」の判定そのものが変わりかねません。右の図のように、期待度数が5未満のセル(赤)が一つでもあると、近似は当てにできません。
ここで自然な疑問が生まれます——近似がダメなら、近似に頼らず正確な確率を直接計算できないのか? できます。それがフィッシャーの正確検定です。次の節で、その「正確さ」がどこから来るのかを掘り下げます。
フィッシャーの正確検定と超幾何分布
周辺度数を固定するという発想
フィッシャー検定の出発点は、大胆な条件付けです。「周辺度数(行計と列計)はすべて与えられたものとして固定する」と決めてしまいます。すると、表の自由度はたった1になります。なぜなら、周辺度数が決まっていれば、セル $a$ の値さえ決めれば残りの $b, c, d$ は引き算で一意に決まるからです($b = (a+b) – a$ など)。
この「周辺度数を固定する」という設定は、壺から玉を取り出す問題そのものになります。全部で $n$ 個の玉があり、そのうち「成功」の玉が $a+c$ 個、「失敗」の玉が $b+d$ 個あるとします。ここから群Aのぶんとして $a+b$ 個を非復元で(戻さずに)取り出すとき、取り出した中に成功の玉がちょうど $a$ 個含まれる確率はいくらか——これがセル $a$ の確率です。

左の壺のイメージのとおり、「総数」「成功の総数」「取り出す数」が固定されている状況で、取り出した成功数 $a$ の分布を 超幾何分布(hypergeometric distribution) と呼びます。右の棒グラフは、その確率分布を実際に描いたものです。
超幾何分布による確率
組み合わせの記号 $\binom{n}{k}$($n$ 個から $k$ 個選ぶ組み合わせ数)を使うと、セル $a$ の確率は次で与えられます。
$$ P(a) = \frac{\dbinom{a+b}{a}\dbinom{c+d}{c}}{\dbinom{n}{a+c}} $$
分母は「全 $n$ 個から成功 $a+c$ 個を選ぶ全パターン数」、分子は「群A($a+b$ 個)の中から成功 $a$ 個を選ぶパターン数」と「群B($c+d$ 個)の中から成功 $c$ 個を選ぶパターン数」の積です。少し変形すると、4つのセルと周辺度数だけで書いた対称的な形になります。分子分母に階乗を代入して整理すると、
$$ P(a) = \frac{(a+b)!\,(c+d)!\,(a+c)!\,(b+d)!}{n!\;a!\,b!\,c!\,d!} $$
が得られます。各周辺度数の階乗の積を、総数の階乗と4セルの階乗の積で割った、覚えやすい形です。この式が、フィッシャー検定が「正確(exact)」と呼ばれる理由そのものです。$\chi^2$ 分布のような連続近似を一切使わず、起こりうる表の確率を組み合わせ論からぴったり計算しているのです。
p値はどう計算するか
p値とは「帰無仮説のもとで、観測と同じかそれ以上に極端な結果が出る確率」でした。フィッシャー検定では、$P(a)$ を使ってこれを直接足し算します。両側検定の標準的な定義は、観測された表の確率 $P(a_{\text{obs}})$ 以下の確率を持つ、すべての可能な表の確率を合計するというものです。
$$ p_{\text{two-sided}} = \sum_{a\,:\,P(a)\,\leq\,P(a_{\text{obs}})} P(a) $$
「観測と同等以下に稀な表」をすべて拾い上げて足す、という意味です。可能な表は、$a$ が取りうる範囲($\max(0, (a+b)+(a+c)-n) \le a \le \min(a+b, a+c)$)で全部列挙できます。その全パターンを描いたのが次の図です。

図の例では、周辺度数(行計 8と12、列計 9と11、$n=20$)を固定し、$a$ を $0$ から $8$ まで動かした9通りの表を並べています。観測 $a=6$ の確率は $P=0.037$ です。これと同等以下の確率を持つ表(赤枠)の確率をすべて足すと、両側p値は $0.065$ になります。グレーの表(観測より起こりやすい中央の表)は除外されます。
この「全列挙して足す」という計算は、$n$ が大きくなると組み合わせ爆発で重くなりますが、2×2程度なら一瞬です。これこそが、小標本でも近似誤差ゼロでp値を出せるフィッシャー検定の強みです。
検定で「差があるかどうか(有無)」はわかりました。しかし実務では「差がどれくらい大きいか(効果の大きさ)」も知りたいものです。次の節で、その指標であるオッズ比と相対リスクを見ていきましょう。
オッズ比と相対リスク
2つの効果量
「治療に効果があった」と言うとき、その効果の大きさを数値で表したい。分割表で代表的な効果量が、オッズ比(odds ratio, OR) と 相対リスク(relative risk, RR) です。
まずオッズとは「成功する確率 ÷ 失敗する確率」のこと。群Aのオッズは $a/b$、群Bのオッズは $c/d$ です。その比を取ったのがオッズ比です。
$$ \mathrm{OR} = \frac{a/b}{c/d} = \frac{ad}{bc} $$
きれいに $ad/bc$ という形になります(クロス積比とも呼ばれます)。一方、相対リスクは「成功する確率そのもの」の比です。群Aの成功確率は $a/(a+b)$、群Bは $c/(c+d)$ なので、
$$ \mathrm{RR} = \frac{a/(a+b)}{c/(c+d)} $$
となります。

どちらを使うべきか
左の定義の対比のとおり、両者は「比べているものが違う」だけです。相対リスクは「確率が何倍か」で直感的に解釈しやすく、コホート研究(集団を追跡する研究)で好まれます。一方オッズ比は、発生率を直接観測できないケースコントロール研究(結果から遡る研究)でも計算できるという数学的な利点があり、ロジスティック回帰とも自然につながります。
右のグラフが重要な性質を示しています。「真のリスク比が2倍」と固定しても、対照群の発生率が低いうちはオッズ比もほぼ2に近い(OR ≈ RR)のに、発生率が高くなるとオッズ比はどんどん大きくなります。まれな事象(発生率が低い)ではORとRRはほぼ一致するが、ありふれた事象ではORがRRを誇張する——これがよく言われる「オッズ比は効果を過大に見せがち」という注意点の正体です。論文を読むときは、報告されているのがORなのかRRなのかを必ず確認しましょう。
ここまでは、2つの群が独立であることを前提にしてきました(治療群と対照群は別人)。しかし「同じ人の治療前と後」のように、データがペアになっている場合は話がまったく変わります。次の節で、その対応ありデータの扱いを見ていきます。
マクネマー検定(対応ありデータ)
対応ありとは何か、なぜ別の検定が要るのか
「治療前と治療後で症状の有無がどう変わったか」を同じ患者で測ると、各患者は2回測定されます。これが対応あり(paired) のデータです。この場合、前と後のデータは独立ではありません。同じ人なので強く相関しています。独立を前提とするカイ二乗検定やフィッシャー検定をそのまま使うと、この相関を無視して誤った結論を出してしまいます。
対応ありの2×2表は、行が「前の状態」、列が「後の状態」になります。すると4つのセルの意味が、独立の場合とはまるで違ってきます。

図のように、対角のセル $a$(前後とも陽性)と $d$(前後とも陰性)は「状態が変わらなかった人」です。彼らは「前と後で違いがあるか」という問いには何の情報も持ちません。情報を持つのは、非対角のセル $b$(前は陽性→後は陰性)と $c$(前は陰性→後は陽性)、つまり「状態が変わった人」だけなのです。
マクネマー統計量の導出
帰無仮説は「変化に方向の偏りがない」、つまり「陽性→陰性になる人数 $b$ と、陰性→陽性になる人数 $c$ は確率的に等しい」です。変化した人の総数 $b+c$ のうち、どちらの方向に変わるかは確率 $1/2$ ずつだと考えます。すると $b$ は二項分布 $\mathrm{Binomial}(b+c, 1/2)$ に従うはずで、その期待値は $(b+c)/2$ です。
観測された $b$ と、期待値 $(b+c)/2$ のズレをカイ二乗の形で測ると、
$$ \chi^2 = \frac{(b – \frac{b+c}{2})^2}{\frac{b+c}{2}} + \frac{(c – \frac{b+c}{2})^2}{\frac{b+c}{2}} $$
となります。ここで $b – \frac{b+c}{2} = \frac{b-c}{2}$、$c – \frac{b+c}{2} = \frac{c-b}{2}$ なので、両項の分子は等しく $\left(\frac{b-c}{2}\right)^2$ です。これを代入すると、
$$ \chi^2 = 2 \cdot \frac{\left(\frac{b-c}{2}\right)^2}{\frac{b+c}{2}} = 2 \cdot \frac{(b-c)^2/4}{(b+c)/2} $$
分子分母を整理すると、$\frac{(b-c)^2/4}{(b+c)/2} = \frac{(b-c)^2}{2(b+c)}$ なので、これを2倍して、
$$ \boxed{\;\chi^2 = \frac{(b-c)^2}{b+c}\;} $$
という非常にシンプルなマクネマー統計量が得られます。対角セル $a, d$ がまったく登場しないことに注目してください。これは帰無仮説のもとで自由度1の $\chi^2$ 分布に従います。なお $b+c$ が小さいとき(おおむね25未満)は、連続性を補正した $\chi^2 = (|b-c|-1)^2/(b+c)$(エドワーズの連続補正)や、二項分布を使った正確なマクネマー検定が使われます。
治療前後の具体例
実際に計算してみましょう。ある治療の前後で症状の有無を調べたデータです。

左の図は、20人の患者それぞれの前後の状態(赤=症状あり、緑=なし)を線で結んだものです。橙色の線が「状態が変わった人」を表します。これを集計すると、改善した人(前あり→後なし)が $b=8$、悪化した人(前なし→後あり)が $c=2$ でした。統計量は
$$ \chi^2 = \frac{(b-c)^2}{b+c} = \frac{(8-2)^2}{8+2} = \frac{36}{10} = 3.6 $$
となり、自由度1の $\chi^2$ 分布から $p \approx 0.058$ が得られます。有意水準5%ではぎりぎり有意になりませんが、改善方向への偏りが見て取れます。この「変化した人だけに注目する」という考え方こそ、対応ありデータの本質です。
マクネマー検定は「2つの条件(前と後)」の比較でした。では、「薬A・薬B・薬Cを同じ患者で順に試す」のように3条件以上を比べたいときはどうするのでしょうか。その拡張がコクランのQ検定です。
コクランのQ検定(3条件以上への拡張)
マクネマー検定を、2条件から $k$ 条件($k \geq 3$)へ一般化したものが コクランのQ検定(Cochran’s Q test) です。同一の被験者に対して $k$ 種類の条件で二値(成功/失敗)の応答を測り、「条件によって成功率に差があるか」を検定します。

左の図のように、各被験者(行)が各条件(列)で成功(○)か失敗(×)かを記録します。$N$ を全成功数、$C_j$ を条件 $j$ の成功数、$R_i$ を被験者 $i$ の成功数とすると、コクランのQ統計量は
$$ Q = \frac{k(k-1)\sum_{j=1}^{k}\left(C_j – \frac{N}{k}\right)^2}{k N – \sum_{i}R_i^2} $$
で定義され、帰無仮説(全条件で成功率が等しい)のもとで自由度 $k-1$ の $\chi^2$ 分布に従います。分子は「各条件の成功数が全体平均 $N/k$ からどれだけばらついているか」を測り、分母は被験者ごとの応答のばらつきで正規化する役割です。
右の図の例では、3条件の成功者数が $3, 4, 9$ と差があり、$Q = 6.2$、自由度2、$p \approx 0.045$ が得られます。5%水準でぎりぎり有意で、「条件によって成功率が違う」と判断できます。$k=2$ のときコクランのQはマクネマー統計量に一致するので、マクネマーはコクランのQの特殊な場合と見ることもできます。
ここまでで、独立・対応あり・2条件・多条件と、状況に応じた検定が出そろいました。では実際のデータを前にして、どの検定を選べばよいのか。次の節で整理します。
どの検定を選ぶか
検定の選択は、たった2つの問いでほぼ決まります。「標本は独立か、対応ありか」と「標本サイズ(期待度数)は十分か」です。これをフローチャートにまとめました。

判断の流れは次のとおりです。
- 対応ありか? 同じ個体を2回(以上)測定しているなら対応あり。別々の個体を2群に分けたなら独立。
- 独立の場合: すべてのセルの期待度数が5以上ならカイ二乗検定。一つでも5未満ならフィッシャー正確検定。標本が大きければどちらもほぼ同じ結果になるので、迷ったら正確検定が安全です。
- 対応ありの場合: 2条件ならマクネマー検定、3条件以上ならコクランのQ検定。
- 効果量を併記: 検定でp値を出すだけでなく、オッズ比 $\mathrm{OR}=ad/bc$ や相対リスク、その信頼区間も報告すると、差の「大きさ」が伝わります。
特に、セルにゼロが含まれるときや総数が数十程度の小標本では、カイ二乗近似が崩れやすいので正確検定を選ぶのが鉄則です。この判断基準を頭に入れたうえで、いよいよPythonで実際に計算してみましょう。
Pythonでの実装
フィッシャー正確検定とカイ二乗の比較
scipy.stats には今回紹介した検定がすべて揃っています。まず、冒頭の新薬の例(治療群14人中11人が治癒、対照群14人中4人が治癒)で、カイ二乗検定とフィッシャー正確検定を比べてみます。
import numpy as np
from scipy.stats import fisher_exact, chi2_contingency
# 2x2分割表 [[治療・治癒, 治療・非治癒], [対照・治癒, 対照・非治癒]]
table = np.array([[11, 3],
[4, 10]])
# カイ二乗検定(連続補正なし)
chi2_stat, p_chi2, dof, expected = chi2_contingency(table, correction=False)
print("=== カイ二乗検定 ===")
print(f"統計量 chi2 = {chi2_stat:.3f}, p値 = {p_chi2:.4f}")
print(f"期待度数 =\n{expected}")
# フィッシャー正確検定(両側)
odds_ratio, p_fisher = fisher_exact(table, alternative="two-sided")
print("\n=== フィッシャー正確検定 ===")
print(f"オッズ比 OR = {odds_ratio:.3f}, p値 = {p_fisher:.4f}")
このコードを実行すると、カイ二乗検定では $p \approx 0.008$、フィッシャー正確検定では $p \approx 0.021$ となります。どちらも5%水準で有意ですが、p値には2.5倍以上の開きがあります。期待度数を見ると全セルが $6.5$ または $7.5$ で、5は超えているものの十分大きいとは言えません。この小標本(各群14人)では、カイ二乗近似がp値を小さめに見積もり、「より有意」と楽観的に判定していることがわかります。安全側に立つなら、フィッシャーの値を採用すべきです。
効果量(オッズ比と相対リスク)を計算する
検定だけでなく、効果の大きさも数値で出しておきましょう。
import numpy as np
a, b, c, d = 11, 3, 4, 10 # table の4セル
# オッズ比 OR = ad / bc
OR = (a * d) / (b * c)
# 相対リスク RR = [a/(a+b)] / [c/(c+d)]
RR = (a / (a + b)) / (c / (c + d))
print(f"オッズ比 OR = {OR:.3f}")
print(f"相対リスク RR = {RR:.3f}")
print(f"治療群の治癒率 = {a/(a+b):.3f}")
print(f"対照群の治癒率 = {c/(c+d):.3f}")
実行すると、オッズ比は $9.17$、相対リスクは $2.75$ になります。治癒率は治療群 $78.6\%$ に対し対照群 $28.6\%$ で、相対リスクの「治療群は対照群の約2.75倍治りやすい」という解釈は直感に合います。一方オッズ比の $9.17$ という大きな値は、治癒という事象がそれなりに高頻度(28〜79%)であるために、前節で見たとおりORがRRを誇張している例です。効果の「大きさ」を一般の人に伝えるなら、RRや治癒率そのものを使うほうが誤解が少ないでしょう。
超幾何分布からp値を手計算で再現する
フィッシャー検定がブラックボックスでないことを確かめるため、超幾何分布から両側p値を自分で組み立て、scipy の結果と一致するか検証します。
import numpy as np
from scipy.stats import hypergeom, fisher_exact
def fisher_two_sided(table):
"""超幾何分布から両側p値を手計算する"""
(a, b), (c, d) = table
n = a + b + c + d
row1 = a + b # 群Aの総数(取り出す数)
col1 = a + c # 成功の総数
# a の取りうる範囲
a_min = max(0, row1 + col1 - n)
a_max = min(row1, col1)
a_range = np.arange(a_min, a_max + 1)
# 各 a の超幾何確率:母集団 n, 成功 col1, 抽出 row1
pmf = hypergeom.pmf(a_range, n, col1, row1)
p_obs = hypergeom.pmf(a, n, col1, row1)
# 観測と同等以下に稀な表の確率を合計
return pmf[pmf <= p_obs + 1e-12].sum()
table = np.array([[6, 2],
[3, 9]])
p_manual = fisher_two_sided(table)
_, p_scipy = fisher_exact(table, alternative="two-sided")
print(f"手計算の両側p値 = {p_manual:.6f}")
print(f"scipyの両側p値 = {p_scipy:.6f}")
実行すると、手計算と scipy のp値はどちらも $0.064777$ で完全に一致します(これは図04で示した例と同じ表です)。scipy.stats.fisher_exact が内部でやっているのは、まさにこの「超幾何分布の確率を全列挙して、観測以下のものを足す」という操作だと確認できました。理論と実装が寸分違わず噛み合っています。
マクネマー検定(治療前後)
次に対応ありデータです。statsmodels の mcnemar を使うのが簡単ですが、ここでは公式どおり手計算もして、両者を比べます。
import numpy as np
from scipy.stats import chi2, binomtest
def mcnemar_test(b, c, correction=True):
"""マクネマー検定。b, c は不一致セル"""
if correction:
stat = (abs(b - c) - 1) ** 2 / (b + c) # 連続補正あり
else:
stat = (b - c) ** 2 / (b + c)
p = chi2.sf(stat, df=1)
return stat, p
# 治療前後:改善 b=8, 悪化 c=2
b, c = 8, 2
stat_plain, p_plain = mcnemar_test(b, c, correction=False)
stat_cc, p_cc = mcnemar_test(b, c, correction=True)
# 二項検定による正確なマクネマー
p_exact = binomtest(min(b, c), b + c, 0.5).pvalue
print(f"補正なし : chi2 = {stat_plain:.3f}, p = {p_plain:.4f}")
print(f"連続補正あり: chi2 = {stat_cc:.3f}, p = {p_cc:.4f}")
print(f"正確(二項): p = {p_exact:.4f}")
実行すると、補正なしで $p \approx 0.058$、連続補正ありで $p \approx 0.114$、正確検定で $p \approx 0.109$ となります。$b+c = 10$ という小さな不一致数では、補正なしの近似がp値を過小評価(有意に近く見せる)していることがわかります。不一致数が少ないときは連続補正版か正確版を使うべき、という先ほどの注意が数値で裏づけられました。
機械学習への応用:2つの分類器を比較する
最後に、本記事の実用的なハイライト——2つの分類器の精度差が統計的に有意かを、マクネマー検定で判定します。同じテストセットで両分類器を評価するので、これは対応ありデータです。
import numpy as np
from scipy.stats import chi2, binomtest
# 同一テストセットでの2分類器の正誤を集計した2x2表
# B正解 B誤り
# A正解 [ n11 , b ] b = Aだけ正解
# A誤り [ c , n00 ] c = Bだけ正解
b = 18 # 分類器Aだけが正解した件数
c = 42 # 分類器Bだけが正解した件数
# マクネマー(連続補正あり)と正確検定
stat_cc = (abs(b - c) - 1) ** 2 / (b + c)
p_cc = chi2.sf(stat_cc, df=1)
p_exact = binomtest(min(b, c), b + c, 0.5).pvalue
print(f"不一致セル: Aだけ正解 b={b}, Bだけ正解 c={c}")
print(f"マクネマー(補正あり): chi2 = {stat_cc:.3f}, p = {p_cc:.5f}")
print(f"正確検定(二項) : p = {p_exact:.5f}")
print("→ p < 0.05 なら2分類器の精度差は有意" if p_cc < 0.05
else "→ 有意差なし")
実行すると、連続補正版で $\chi^2 \approx 8.82$、$p \approx 0.003$、正確検定で $p \approx 0.003$ となり、いずれも5%水準で有意です。分類器Bだけが正解した件数(42)が、Aだけ正解した件数(18)を大きく上回っているので、「分類器Bのほうが有意に優れている」と結論できます。

この図が示すように、分類器比較で見るべきは「両方正解」「両方不正解」のセルではなく、意見が割れた不一致セル $b, c$ だけです。両方が正解(520件)や両方が不正解(120件)の例は、優劣の判断材料になりません。「全体の正解率を単純比較してt検定する」といった誤った手続きを避け、ペア構造を正しく扱うマクネマー検定を使うことが、機械学習論文でも標準的な作法になっています。
まとめ
本記事では、2×2分割表に対する検定を、小標本・対応ありという2つの落とし穴に注目して解説しました。
- カイ二乗検定の限界: カイ二乗統計量が $\chi^2$ 分布に従うのは近似であり、期待度数が5未満のセルがあるとp値が信頼できなくなる。
- フィッシャー正確検定: 周辺度数を固定すると、セル $a$ は超幾何分布 $P(a)=\binom{a+b}{a}\binom{c+d}{c}/\binom{n}{a+c}$ に従う。観測以下の確率の表をすべて足し上げることで、近似誤差ゼロの厳密なp値が得られる。
- オッズ比と相対リスク: $\mathrm{OR}=ad/bc$ と $\mathrm{RR}$ は効果量。まれな事象ではほぼ一致するが、ありふれた事象ではORがRRを誇張する。
- マクネマー検定: 対応ありデータでは、状態が変わらなかった対角セルは情報を持たず、不一致セルだけが効く。統計量は $\chi^2=(b-c)^2/(b+c)$。不一致数が少なければ連続補正版か正確版を使う。
- コクランのQ: マクネマーを3条件以上に拡張したもの。$k=2$ でマクネマーに一致する。
- 検定の選択: 「独立か対応ありか」「期待度数は十分か」の2つでほぼ決まる。迷ったら正確検定が安全。
- 応用: 医療の治療効果判定、A/Bテスト、そして同一テストセットでの分類器比較(マクネマー)。
これらの検定は、p値だけでなくオッズ比や相対リスクといった効果量とセットで報告することで、初めて「差があるか」と「どれくらいの差か」の両方を語れるようになります。
次のステップとして、以下の記事も参考にしてください。