A/Bテスト設計の基礎
サンプル・MDE・検定
A/Bテストの目的は「どちらが良いか」を統計的に切り分けることです。テスト結果が「有意差なし」で終わるか、明確な打ち手につながるかは、開始前にMDE・サンプルサイズ・検出力を揃えられたかに大きく依存します。実装と結果分析は型化できます。
A/Bテストの品質は、テスト開始前に MDE(検出可能効果量)・必要サンプルサイズ・検出力 を決めた事前設計で大半が決まります。比較対象が比率(CVR・CTR)ならカイ二乗検定、平均値(滞在時間・売上)ならt検定(Welchのt検定)、外れ値や少サンプルならマン・ホイットニーのU検定。途中で結果を覗き見して止める「ピーキング」は偽陽性を増やすため、事前計画した期間まで待つのが基本です。
01.まず結論:A/Bテストは『事前設計』で結果の大半が決まる
A/Bテストの実装は 3フェーズ に分解できます。各フェーズでつまずきポイントが違うので、最初に全体像を押さえます。
| フェーズ | やること | つまずきポイント |
|---|---|---|
| 事前設計 | 仮説・KPI・MDE・必要サンプルサイズ・検出力・テスト期間を決める | MDE設定が小さすぎてサンプルが足りない/大きすぎて差が見えない |
| 実装 | 割付(ランダム化)・タグ実装・データ収集・ガードレール指標の設定 | ユーザー粒度の割付ミス、計測欠損、ボット混入 |
| 分析 | 計画通りの期間まで待ち、適切な検定で有意性を確認、効果量と信頼区間を併記 | p 値だけ見る、早期停止(ピーキング)、多重比較未補正 |
02.MDE・サンプルサイズ・検出力の3点セット
A/Bテスト設計の中核は3つの数字です。これを事前に決めずにテストを回すと、有意になるまで延々と続けるか、見たい効果を見つけられずに終わります。
| 概念 | 意味 | 実務での目安 |
|---|---|---|
| MDE(Minimum Detectable Effect) | 検出したい最小の効果量(例:CVR +0.5pt、滞在時間 +5秒) | ビジネス的に意味のある変化を逆算。小さいほど大サンプル |
| サンプルサイズ(n) | テストに必要な人数・件数 | MDEと検出力で逆算される。1群あたり数千〜数万が普通 |
| α(有意水準) | 第一種の過誤(差がないのに『ある』と誤判定)の許容率 | 通常 0.05。重要な意思決定では 0.01 |
| 1-β(検出力/Power) | 差があるときに気づける確率(第二種の過誤の裏返し) | 通常 0.8。安全寄りに 0.9 を取ることも |
| ベースラインCVR | 現状の基準値(既存A群のCVR) | 過去90日などの平均から推定 |
図:MDE・サンプルサイズ・検出力の三項関係
有意水準αを0.05、検出力を0.8と固定すると、MDE と必要サンプルサイズは反比例。小さな差を見つけたいなら、より多くのサンプルが必要になる。
MDE
検出したい差の最小値
小さいほど高精度。CVR +0.5pt を捉えたいか、+2pt で良いか
サンプルサイズ(n)
テストに必要な人数・件数
多いほど精度が上がる。母集団とトラフィックに依存
検出力(Power)
差があるときに気づける確率
通常 0.8。小さい差を見つけたいなら大サンプルが必要
どれかを変えれば他のどれかも動く。テスト開始前にこの3つをセットで決めるのが基本。
ベースラインCVR 3%、MDE +0.5pt(つまり 3.5% に上げたい)、α=0.05、検出力 0.8 のとき、必要サンプルは 1 群あたりおおむね 19,700 件(合計約 4 万件)です。MDEを +1pt(4% を狙う)に緩めると、1 群 5,300 件程度(合計約 1 万件)で足ります。小さい差を狙うほど、必要サンプルは二次関数的に増えます(差を半分にすると必要件数は 4 倍)。設計時に「現実的にテスト期間内に集まる規模か」を必ず確認します。
# 必要サンプルサイズの計算(statsmodels)
from statsmodels.stats.power import NormalIndPower
from statsmodels.stats.proportion import proportion_effectsize
baseline = 0.03 # 現行CVR
mde_abs = 0.005 # 検出したい絶対差(+0.5pt)
target = baseline + mde_abs
# 効果量(Cohen's h)を出してから NormalIndPower で n を逆算
h = proportion_effectsize(target, baseline)
analysis = NormalIndPower()
n = analysis.solve_power(effect_size=h, alpha=0.05, power=0.8, ratio=1)
print(f"1群あたり必要サンプル: 約 {int(n)} 件") # 約 19,700 前後(合計 約 4 万件)同じ逆算は、次のツールに現行CVR・MDE・有意水準・検出力を入れればその場で計算できます。1群あたりと合計の必要サンプル数に加え、1日あたりの想定流入を入れればテストに何日かかるか、MDEを緩める/厳しくしたときに必要数がどう動くかまで確認できます。サンプルサイズ設計の考え方はサンプルサイズ設計と検出力の基礎で詳しく扱っています。
ベースラインCVR・MDE・有意水準・検出力を入れると、1群あたり/合計の必要サンプル数と所要日数を逆算します(ブラウザ内で計算、サーバー送信なし)。
→ 目標CVR 3.50%(相対 +16.7%)
有意水準α:差がないのに「差あり」と誤る確率の上限(偽陽性)。通常5%(α=0.05)。誤って施策を採用する代償が大きいときだけ1%(α=0.01)にします。
検出力:本当に差があるとき、それに気づける確率。慣例的に0.80(5回に1回は見逃す設定)。見逃しの代償が大きい意思決定では0.90に上げますが、必要サンプルは約34%増えます。
両側/片側:改善・悪化どちらの差も見るなら両側(通常はこちら)。「上がる」方向だけを検定したいときだけ片側にします。片側のほうが必要サンプルは少なくなります。
効果量 Cohen's h = 0.0282(ベースライン3.00% → 目標3.50%)。2標本の比率の逆正弦変換にもとづく正規近似で、有意水準5%・検出力0.80・両側検定の条件です。
| 検出したい差(MDE) | 1群あたり | 合計 | 所要日数 |
|---|---|---|---|
| +1.00pt(2倍) | 5,276 | 10,552 | 約4日 |
| +0.50pt(現在) | 19,716 | 39,432 | 約12日 |
| +0.25pt(半分) | 76,007 | 152,014 | 約47日 |
検出したい差を半分にすると、必要サンプルはおよそ4倍に膨らみます(効果量の2乗に反比例)。「もっと小さい差まで見たい」は「テスト期間が4倍になってもよいか」とほぼ同義です。
算出した合計サンプルを日次の流入で割り、テスト期間が現実的かを確かめます。期間内に集まらないときは、勘で始めずMDEを緩める・上流の指標で測る・対象を絞るといった設計側の調整で折り合いをつけてください。テスト後の有意差判定はA/Bテスト有意差判定ツールが使えます。
サンプルサイズ設計からA/Bテストの効果検証・レポーティングまでの伴走はWeb運用代行サービス「TANTOU」で支援しています。
03.カイ二乗検定|CVR・CTRなど比率の差を見る
CVR・CTR・購入率・クリック有無のように 「成功した/しなかった」の二値 の比率を A/B で比較するときは、カイ二乗検定(χ²検定)または比率のZ検定を使います。観測度数と「もし差がなかった場合の期待度数」のズレを二乗して足し合わせ、ズレが偶然で説明できるかを判定する仕組みです。この2つの検定が使える理論的な背景(CVRが二項分布に従い、サンプルが十分大きいと正規近似できること)は統計的仮説検定の基礎で整理しています。
図:2×2分割表(カイ二乗検定の入口)
例:LP の CTA コピーを「資料請求」(A群: 現行) → 「無料で試す」(B群: 新案) に変更したテストの集計。結果(CVあり/なし)×群(A/B)の 2×2 表で表現し、観測度数と「もし差がなかった場合の期待度数」のズレからカイ二乗統計量を計算する。
120
CVR 2.4%
4,880
160
CVR 3.2%
4,840
この例では新案 B が CVR +0.8pt(2.4% → 3.2%)。カイ二乗検定でこの差が偶然で説明できるかを確認する。
# カイ二乗検定の実装(scipy)
import numpy as np
from scipy.stats import chi2_contingency
# CV あり / CV なし
table = np.array([
[120, 4880], # A群
[160, 4840], # B群
])
chi2, p, dof, expected = chi2_contingency(table)
print(f"カイ二乗統計量: {chi2:.3f}")
print(f"p値: {p:.4f}") # 0.05 を下回れば有意
# 効果量と信頼区間も併記する(p値だけでは不十分)
from statsmodels.stats.proportion import proportions_ztest, confint_proportions_2indep
count = np.array([120, 160])
nobs = np.array([5000, 5000])
z, p_z = proportions_ztest(count, nobs)
ci = confint_proportions_2indep(count[1], nobs[1], count[0], nobs[0])
print(f"CVR差の95%CI: {ci}")カイ二乗検定はサンプルが少なく、期待度数が5未満のセルがあると近似精度が落ちます。たとえば「A群でCVが3件、B群で5件」のような小さなテストでは、Fisher の正確検定(scipy.stats.fisher_exact)を使う方が安全です。期待度数を必ず出力して確認するのが習慣化しやすい運用です。
上のコード例と同じ計算(比率のz検定=イェーツ補正なしのカイ二乗検定)は、次のツールで手元のデータからその場で確認できます。初期値には本節の数値例(A: 5000中120CV、B: 5000中160CV)を入れてあります。
各パターンの訪問数とCV数を入れると、比率のz検定(カイ二乗検定と同等)でその場で有意差を判定します(ブラウザ内で計算、サーバー送信なし)。
差が偶然生じる確率(p値)が有意水準5%(α=0.05)を下回りました。
差が偶然である確率はp = 0.015と小さく、有意水準5%を下回っています。勝ちパターンを本番に反映し、次の改善テストに進める段階です。ただし、テスト期間中に何度も結果を確認して「有意になった瞬間に止めた」場合は偽陽性の可能性が高まるため、事前に決めた期間・サンプルサイズを満たしているかを確認してください。
LP・フォーム・CTAの改善テストを継続的に回す体制づくりはWeb運用代行サービス「TANTOU」で支援しています。
04.t検定とWelchのt検定|平均値の差を見る
滞在時間・客単価・PV/セッション・スクロール深度のような連続値の平均を A/B で比較するときは t 検定を使います。等分散を仮定できれば普通の独立2標本t検定、できなければ Welch のt検定が選択肢です。
図:t検定は「平均の差」が「ばらつき」に比べて大きいかを判定する
例:LP のデザイン変更による滞在時間の比較。A群(現行)平均 120 秒、B群(新案)平均 145 秒。t 統計量 = 平均の差 ÷ 標準誤差(群内のばらつき)。差が大きく、群内のばらつきが小さいほど統計量が大きく、有意になりやすい。
A群(現行LP)
平均滞在時間 120 秒 / 標準偏差 30 秒
B群(新LP)
平均滞在時間 145 秒 / 標準偏差 30 秒
2つの山がほぼ重なっていれば差は偶然の可能性が高い。山が離れているほど(または山が細い=ばらつきが小さいほど)、t 統計量が大きくなる。
| 検定 | 前提 | ひとこと |
|---|---|---|
| 独立2標本 t検定(Student) | 両群が独立/正規分布/等分散 | 実務では等分散を仮定しづらいので、Welch をデフォルトにするチームが多い |
| Welch のt検定 | 両群が独立/正規分布(等分散は不要) | scipy では `ttest_ind(..., equal_var=False)` |
| 対応のあるt検定 | 同一被験者の前後比較 | A/Bテストでは基本的に使わない(同一ユーザーに両方を見せないため) |
# Welch のt検定の実装(scipy)
import numpy as np
from scipy.stats import ttest_ind
a = np.array([...]) # A群の滞在時間(秒)
b = np.array([...]) # B群の滞在時間(秒)
stat, p = ttest_ind(a, b, equal_var=False) # Welch
print(f"t統計量: {stat:.3f}")
print(f"p値: {p:.4f}")
# 95%信頼区間(差の推定)
from scipy.stats import t as t_dist
mean_diff = b.mean() - a.mean()
se = np.sqrt(b.var(ddof=1)/len(b) + a.var(ddof=1)/len(a))
dof = (b.var(ddof=1)/len(b) + a.var(ddof=1)/len(a))**2 / (
(b.var(ddof=1)/len(b))**2/(len(b)-1) + (a.var(ddof=1)/len(a))**2/(len(a)-1)
)
ci = mean_diff + np.array([-1, 1]) * t_dist.ppf(0.975, dof) * se
print(f"平均差の95%CI: {ci}")t 検定は理屈上「分布が正規」を仮定しますが、サンプル数が大きければ平均値の分布は中心極限定理で正規に近づくため、実務では各群 30〜50 件を超えるあたりからほぼ気にしなくて良くなります。むしろ警戒すべきは 大きな外れ値 と 分布の歪み。客単価のような対数正規分布なデータは、対数変換してから t 検定をかけるか、後述のマン・ホイットニーU検定を使うのが安全です。
05.マン・ホイットニーのU検定|分布を仮定しない検定
売上・客単価・滞在時間のように 分布が歪んでいる、外れ値が多い、または サンプルが少ない ときは、ノンパラメトリック検定の代表格である マン・ホイットニーのU検定(Wilcoxon の順位和検定)が使えます。値そのものではなく順位を使うので、外れ値や対数正規分布に強い性質を持ちます。
図:U検定は「値」ではなく「順位」で比較する
例:EC サイトの客単価(円)の比較。B群に 1 件だけ 50,000 円の外れ値が混ざると、生の値で見た平均は外れ値に引きずられる。順位に変換してから平均(順位の合計)を比較すると、外れ値の影響が圧縮される。
生の値で比較(t検定の発想)
A群(現行)
3,000 / 3,200 / 3,500 / 3,800 / 4,200
平均: 3,540円
B群(新案)
3,300 / 3,700 / 4,000 / 4,500 / 50,000
平均: 13,100円 ← 外れ値 50,000 円で歪む
順位で比較(U検定の発想)
順位平均: A 4.2 / B 6.8
生の値の平均は 50,000 円の外れ値ひとつで大きく動くが、順位は最大でも「10 位」に丸まる。外れ値に強いのがランクベース検定の本質。
| こういう場面 | 理由 | 代替案 |
|---|---|---|
| 客単価・売上の比較 | 右に裾の長い対数正規分布。外れ値が多い | U検定/log変換+t検定 |
| サンプルが少ない実験 | 中心極限定理に頼れない | U検定/Bootstrap |
| 順位データ・満足度スコア | 等間隔性を仮定しづらい | U検定/Kruskal-Wallis(3群以上) |
| ヒストグラムが二峰性 | 平均が分布の代表値にならない | U検定/中央値の差で語る |
# マン・ホイットニーのU検定(scipy)
import numpy as np
from scipy.stats import mannwhitneyu
a = np.array([...]) # A群の客単価
b = np.array([...]) # B群の客単価
stat, p = mannwhitneyu(a, b, alternative="two-sided")
print(f"U統計量: {stat:.1f}")
print(f"p値: {p:.4f}")
# 効果量(rank-biserial correlation)も併記
n1, n2 = len(a), len(b)
r_rb = 1 - 2 * stat / (n1 * n2)
print(f"効果量 r: {r_rb:.3f}")06.多重比較問題と早期停止(ピーキング)の落とし穴
A/Bテストの統計的判定でハマりやすい2大トピックが、多重比較問題とピーキング(覗き見停止)です。どちらも偽陽性(差がないのに「ある」と判定する)を増やします。
| 落とし穴 | 起きること | 対処 |
|---|---|---|
| 多重比較問題 | α=0.05 で 20 個の独立テストを回すと、1 個は偶然有意になる確率がほぼ100% | Bonferroni 補正(α / 比較数)/FDR(Benjamini-Hochberg) |
| ピーキング(早期停止) | 毎日結果を見て『有意になった瞬間に止める』と、偽陽性率は名目αの数倍 | 事前計画した期間まで待つ/逐次検定(mSPRT, AGILE)で補正 |
| 後付け仮説検定(HARKing) | テスト後にセグメントを切って『この層で有意』と探すと、偽陽性が爆発 | セグメント分析は事前登録/補正付きで実施 |
| 勝者選択バイアス | 勝った方の効果量は過大評価されやすい | 効果量は信頼区間付きで報告/フォローアップテストで再確認 |
図:ピーキングを許すと偽陽性率が名目αの 5〜6 倍まで膨れる
名目の有意水準を α=0.05(5%)に設定しても、毎日テスト結果を見て「有意になった瞬間に止める」運用では、テスト終了までの累積偽陽性率が大きく増える。30 日見て止めると約 28%(Armitage et al. のシミュレーション目安)。
1 回(事前計画通り)= 名目通り 5%。覗き見回数が増えるほど実効αが増える。点線が名目αのライン。
A/Bテストを毎日見て、p値が 0.05 を切った瞬間に止める運用は、毎日カイ二乗検定を新しく回しているのと同じです。テスト期間が30日なら30回の検定を重ねることになり、偽陽性率は名目の 5% を大きく上回ります。同じ条件同士を比べる A/A テストでさえ、毎日ピーキングして止めれば相当な割合が「有意」と誤判定されます。事前計画した期間まで待つか、Sequential Probability Ratio Test(SPRT)や mSPRT のような逐次検定を使うのが正しい対処です。
07.実務でつまずく落とし穴と対処
| 落とし穴 | 中身 | 対処 |
|---|---|---|
| Simpson のパラドックス | 全体では B が勝つのに、セグメント別に見ると全セグメントで A が勝つ/その逆 | セグメント別の効果量を併記。割付前のユーザー属性が均等かを確認 |
| 新奇性効果(Novelty Effect) | 新しい UI・コピーは最初だけクリックされる | テスト期間を2週間以上取り、後半の差で評価 |
| Primacy 効果(既存ユーザーの慣れ) | 既存ユーザーは新UIを嫌い、最初は数字が下がる | 新規/既存ユーザーに分けて分析 |
| ネットワーク効果・SUTVA違反 | ユーザー同士が干渉する(SNS・マーケットプレイス) | クラスター割付・スイッチバック実験 |
| ガードレール指標の悪化 | 目的指標は伸びたが、別の重要指標(離脱率・読み込み時間)が悪化 | 目的指標とガードレール指標を必ずセットで監視 |
| サンプル比率の歪み(SRM) | A:B=50:50 のはずが実際は 52:48 など、割付に偏りが出ている | テスト開始直後に SRM 検定(カイ二乗)でサニティチェック |
| A/Aテスト省略 | 実装のバグや計測ズレに気づけない | 本番A/Bの前にA/Aテストで偽陽性率を確認 |
p 値は「差があるとは言えるか」を二値で答える指標です。「どれくらい差があるか」「どれくらいの不確実性があるか」までは答えません。本番運用前の報告では、p 値とあわせて効果量(絶対差・相対差・Cohen's d など)と95% 信頼区間を必ず併記します。「CVR +0.5pt(95%CI: +0.2pt 〜 +0.8pt), p=0.003」のように書くと、意思決定に必要な情報がすべて揃います。
08.よくある質問(FAQ)
最低何件あればA/Bテストできますか?
必要サンプルは「ベースラインCVR」「検出したいMDE」「有意水準」「検出力」で決まります。CVR 3%・MDE +0.5pt・α=0.05・検出力 0.8 で、1 群あたり約 19,700 件(合計 約 4 万件)が目安です。トラフィックが少ない BtoB サイトでは、MDEを +1〜2pt に緩めるか、CVRより上流のクリック率や離脱率(サンプル効率の良い指標)でテストする、もしくは事前にCVに転換しやすいセグメントを絞ってテストする、などの設計工夫が必要です。
p値が0.05を超えたら必ず棄却(差がないと判断)すべきですか?
p 値だけで二値判断しない、が原則です。p=0.07 で効果量が大きく信頼区間が魅力的なら、サンプルを追加して検出力を上げるか、別期間で再テストする選択肢があります。逆に p=0.04 でも効果量がビジネス的に意味のない小ささなら、勝者と判定しない方が健全です。「統計的有意」と「実務的に意味のある差」は別物で、両方を満たして初めて採用が正しい判断になります。
AI で生成したコピーや LP をA/Bテストする際の注意点は何ですか?
通常のA/Bテストと同じ設計(MDE・サンプル・検出力)に加えて、AI(ChatGPT、Claude、Geminiなど)生成物の品質チェック(事実性・トーン・SEO観点)を必ず通します。AIで簡単にバリアントを増やせるため、つい多くのパターンを同時に走らせがちですが、テスト数に応じて Bonferroni か FDR で多重比較補正をかけるのが安全です。勝ったバリアントの効果量は過大評価されやすいので、本番展開前に独立期間で再テストするとさらに堅牢になります。
多くのバリアント(A/B/C/D…)を同時にテストして良いですか?
可能ですが、検定数が増える分だけ偽陽性のリスクが上がるので、Bonferroni 補正(α を比較数で割る)か FDR(Benjamini-Hochberg)で補正します。バリアント数が増えるとそれぞれの群に行くサンプルも減り、必要トラフィックが膨らむので、無限に増やせるわけではありません。実務的には A/B/C 程度、あるいは多腕バンディット(Multi-Armed Bandit)で動的に最適配分する方が、トラフィック効率が良くなります。
早期停止は絶対にダメですか?
ナイーブな早期停止(毎日見て有意になったら止める)は、偽陽性率が名目の数倍に跳ね上がるため避けます。どうしても早く止めたいときは、逐次検定の枠組み(SPRT、mSPRT、AGILE、Group Sequential Design)を使って、覗き見しても α が制御されるよう設計します。最近の商用実験プラットフォームの多くはこの仕組みを内蔵しています。設計時に「早期停止を許可するか」を決め、許可するなら逐次検定対応のプラットフォームを選ぶ、というのが運用しやすい指針です。
A/AテストとSRMチェックは毎回必要ですか?
実験プラットフォームを立ち上げた直後は、A/A テスト(同条件同士の比較)で偽陽性率がおおむね 5% に収まるかを確認するのが基本です。本番A/Bテストでは、開始から数時間〜1日後に SRM 検定(割付比率がカイ二乗で帰無仮説 1:1 から外れていないか)を必ず実施します。SRM が出ていたら割付・タグ実装にバグがある可能性が高く、結果を信用しないで停止・修正します。SRM チェックは1行で書けるので、テスト開始直後の標準フローに組み込むのがおすすめです。
09.まとめ
A/Bテストは「事前設計 → 実装 → 分析」の3フェーズで型化できます。事前設計で MDE・サンプルサイズ・検出力を決め、実装でランダム化と SRM サニティチェックを行い、分析で比較対象に応じた検定(比率はカイ二乗、平均はWelchのt、外れ値はマン・ホイットニーU)を使い、p値・効果量・95%信頼区間を必ず併記する。これだけで、A/Bテストの大半の事故は防げます。
最後にもう一度。覗き見停止は最大の偽陽性源。事前計画した期間まで待つか、逐次検定で補正する。これが守れるかどうかが、A/Bテスト運用の成熟度を分けます。
データ分析でよく使うアルゴリズム・指標まとめ
類似度・一致度・予測モデル評価の3カテゴリで指標を整理した総合解説です。
予測モデル評価の指標と使い分け
F1・ROC-AUC・MAE・RMSE・Pearsonなど予測モデルの代表指標を整理します。
SEO分析の統計入門|順位別CTR・カニバリ検知・記事の鮮度低下
Search Console データを統計的に読み解くための入門。期待CTR・4象限分析・介入分析までを整理します。
一致度・信頼性の指標と使い分け
評価者・モデル間の一致度を測る Cohen's Kappa などを整理します。
A/Bテスト設計と分析体制の構築をご相談ください
A/Bテストの仮説設計・サンプルサイズ計算・統計分析・実験プラットフォーム選定までの伴走支援を行っています。お気軽にお問い合わせください。
データ分析・アルゴリズム 基礎知識集
一覧に戻る →全体像とカテゴリ早見
データの可視化
個別指標カテゴリ
統計的推測の基礎
- ›統計的仮説検定の基礎|p値・過誤・信頼区間
- ›ベイズ統計の基礎|事前分布・事後分布・ベイズ更新
- ›相関分析の基礎|ピアソン・スピアマンと相関≠因果
- ›サンプルサイズ設計と検出力の基礎
- ›A/Bテスト設計の基礎|サンプル・MDE・検定(この記事)

