Playground 7:A/Bテストの実験室
計量経済学II(ブラウザ上でRが動きます)
- このページのRコードは、あなたのブラウザの中で動いている(WebAssembly + webR)。インストールは一切不要。
- 初回だけ、ページ読み込みに30秒〜1分かかる(R本体とパッケージのダウンロード)。2回目以降はキャッシュで速くなる。
- 各セルのコードは自由に書き換えて「Run Code」で実行できる。何をどう壊しても誰にも迷惑はかからない。おかしくなったらページを再読み込みすれば元に戻る。
- 元ネタは講義ノート(
lecture7.html)。ここでは「数値をいじって挙動を体感する」ことに集中する。
実験1:検出力シミュレーター — 「見つけられる確率」を測る
真に効果がある施策でも、\(N\)が足りなければ検定は「有意」と言ってくれない。ここでは真の効果量・サンプルサイズ・アウトカムのばらつきを自分で決め、その世界でA/Bテストを200回繰り返して、p < 0.05になった割合(= 検出力)を数える。2群の平均比較で検出力\(1-\beta\)を達成するのに必要な片群サンプルサイズは
\[ n = \frac{2 \sigma^2 (z_{1-\alpha/2} + z_{1-\beta})^2}{\tau^2} \]
で近似できる(\(\tau\)は真の効果、\(\sigma\)はアウトカムのSD)。シミュレーションの検出力がこの公式とどれくらい一致するかも見る。
true_effect <- 150(効果を半分)にすると、「検出力80%に必要なN」は何倍になるか。予想してから実行しよう。sd_outcome <- 6000(ばらつき2倍。売上のように分散の大きい指標を想像しよう)にすると、必要Nは何倍になるか。- 上の2つが同じ倍率になったのは偶然だろうか。公式の中で\(\tau\)と\(\sigma\)がどういう形で入っているかから説明できるか?
実験2:peekingの罠 — 覗くほどType I errorが膨らむ
真の効果がゼロの実験を200回行い、「途中経過を\(k\)回チェックして、一度でも有意なら『効果あり』と宣言して止める」という運用の誤検出率(Type I error)を\(k\)ごとに数える。最後に1回だけ検定する\(k=1\)なら、誤検出率は設計通り5%前後になるはずだ(MC 200回なので数ポイントはぶれる)。毎日ダッシュボードを眺めて「有意になった瞬間に展開」する運用が何を壊すかを見よう。
n_checks_fine <- 40、k_list <- c(1, 2, 5, 10, 20, 40)にして、40回覗くと誤検出率がどこまで膨らむか確認しよう。n_total <- 10000に増やしても膨張は消えないことを確認しよう。これはサンプルサイズの問題ではなく、検定を繰り返すという運用の問題である。- このコードで誤検出を膨らませている「犯人」はどの行だろうか。
any(...)の行を「最後のチェックだけで判定」に書き換えたら、\(k\)によらず5%前後に戻るだろうか?
実験3:ITTとTOT — 「配る効果」と「使う効果」は別物
クーポンは配っても全員が使うわけではない。配信\(Z\)はランダムだが、使用\(X\)は顧客の自己選択で決まる(購買意欲の高い人ほど使う)。このとき配信の効果(ITT)と使用の効果(TOT)は別の量である。ランダム割り当て・first stage・排除制約・monotonicityに加え、one-sided noncompliance(配られない人は使えない)が成立すれば、実際の使用者はcomplierなので
\[ \text{TOT} = \frac{\text{ITT}}{P(X = 1 \mid Z = 1)} \]
というWald推定量で結ばれる(分母は配信群の使用率)。一方、実務で頻出の「使用者vs非使用者」の単純比較はセレクションで汚染される。3つの数字を並べて見比べよう。
complianceを0.8、0.4、0.2と下げて、ITTとWald(TOT)の乖離がどう開くかを見よう。ITTはおおよそ「TOT × 使用率」で縮んでいく。使用率が下がるとWald推定量のぶれも大きくなることに注意。1500 * abilityの1500を0にして(セレクションを消して)、単純比較が真のTOTにほぼ一致することを確かめよう。単純比較のバイアスの正体は施策ではなく「使う人はもともと違う」ことにある。- 1500を-1500(購買意欲の低い人ほどクーポンを使う世界)にしたら、単純比較は過大評価と過小評価のどちらになるか。予想してから実行しよう。
実験4:CUPED — 実験前データで分散を削る
実験1で見た通り、検出力は\(N\)だけでなくアウトカムの分散でも決まる。CUPEDは、実験前の同じ指標\(X\)(例:実験前30日の購買額)を使ってアウトカムを\(Y_i - \theta (X_i - \bar X)\)と調整する(\(\theta\)は\(Y\)を\(X\)に回帰した係数)。\(X\)と\(Y\)の相関を\(\rho\)とすると、調整後の分散は
\[ \text{Var}(Y^{c}) = \text{Var}(Y) (1 - \rho^2) \]
になる(母集団の最適係数を使う理論式)。つまりSEは\(\sqrt{1 - \rho^2}\)倍に縮む。有限標本で\(\theta\)も推定する場合は毎回の保証ではないので、調整後SEを実際に確認する。
rhoを0.3と0.9にして、SEの縮み方を比べよう。削減率は\(\rho^2\)で効くので、0.3ではほとんど削れないが、0.9では劇的に縮む。実験前指標の「予測力」がすべてを決める。true_ate <- 0にしても、推定値が0付近のままSEだけが縮むことを確認しよう。CUPEDは効果を作り出さない。見つけやすくするだけである。- \(\rho = 0.6\) のCUPEDは、\(N\)を何%増やしたのと同じ価値があるか。実験1の公式(必要Nは分散に比例する)とつなげて考えてみよう。
次に読むもの
- 講義ノート本体:
lecture7.html(ランダム化推論・MDE公式・大規模実験の落とし穴集の完全版) - coding課題:
assignment7.qmd(ECサイトのメールクーポン実験を題材に、ITT/TOT・CUPED・peeking診断を今日の手順でゼロから実装する)