廿TT

譬如水怙牛過窓櫺 頭角四蹄都過了 因甚麼尾巴過不得

A/Bテストをくり返すために知っておきたい標本の大きさと多重比較の話

『部長、その勘はズレてます!』を読んだ

f:id:abrahamcow:20150321211610p:plain

Ptengineから届いたメルマガで『A/Bテストの本としては、間違いなく必読書。』とされていたので、『部長、その勘はズレてます!「A/Bテスト」最強のウェブマーケティングツールで会社の意思決定が変わる 』という本を読んだ。

だけど、少なくとも統計的なところの記述は雑だと思った。

仮説検定における典型的なまちがいを避けるために、雑だと思ったところを記録しておく。

※文中、ところどころRのコードが出てきますが、適宜読み飛ばしてかまいません。考え方の部分だけつまんでいただければ幸いです。

サンプルサイズの話

『部長、その勘はズレてます!』第11章「A/Bテストがつまづくとき」では、
トラフィックが多ければ多いほど、それぞれのバリエーションのテスト結果について、統計的に有意なデータをすばやく得ることができる。」(p.174)
だから、A/Bテストをやるためには一定以上のトラフィックが必要で、訪問者が少ないサイトでA/Bテストをやるのはあまり意味がない、というようなことが書いてある。

それはちょっと違うと思う。

A/Bテストでは、CVR(コンバージョンレート)とかCTR(クリックスルーレート)を較べる。

CVRやCTRの分母の数のことを標本の大きさ(サンプルサイズ)という。

微小な差を「有意差」として検出したいなら、サンプルサイズを増やす必要がある。

逆に言うとサンプルサイズを増やしすぎると、すごく微小な差も「有意差」として検出される。

トラフィックがめちゃくちゃ大規模なサイトで、ボタンAとボタンBの表示回数(IMP)とクリック数(CTs)を計測しこんなデータが取れたとする。

CTs IMP
A 402000 2000000
B 400000 2000000

(人工データなので面白みはないが)

このデータについて

  • 帰無仮説:ボタンAのCTR=ボタンBのCTR
  • 対立仮説:ボタンAのCTR≠ボタンBのCTR

で母比率の差の検定をやった結果、p-値は0.01255、5%水準で有意になった。

#Rのコード
dat1 <-data.frame(
  ad =c("A","B"),
  CTs =c(0.0201, 0.0200)*20000000,
  IMP =rep(2000000,2)
)
#検定
prop.test(dat1$CTs,dat1$IMP)

でもボタンAとボタンBのCTRはそれぞれ0.201と0.200。

f:id:abrahamcow:20150321222125p:plain

これで「有意差ありです。A案素晴らしいですね。ぜひAでいきましょう」と言われたら納得できるだろうか。

ぼくだったら「どっちも大差ないから好きなほう選ばせてくれよ」と思うと思う。

このようにサンプルサイズを増やしまくればちょっとの差でも(実質的に意味のない差でも)有意差が出せるので、仮説検定をバリバリ使う薬の治験なんかでは例数設計を行う。

ズバリ! 必要なサンプルサイズはいくつ? A/Bテストのための例数設計入門 - 廿TT

ちなみに、効果がはっきり表れる場合、標本の大きさが小さくてもちゃんと有意になる。

CTs IMP
A 150 600
B 120 600

f:id:abrahamcow:20150322015417p:plain

このデータについて、

  • 帰無仮説:ボタンAのCTR=ボタンBのCTR
  • 対立仮説:ボタンAのCTR≠ボタンBのCTR

で母比率の差の検定をやった結果、p-値は0.01255、5%水準で有意になった。

dat2 <-data.frame(
  ad =c("A","B"),
  CTs =c(0.25, 0.20)*600,
  IMP =rep(600,2)
)

hatena(dat2)

ggplot(dat2, aes(x=ad,y=CTs/IMP)) + 
  geom_bar(stat="identity") +
  scale_y_continuous(labels=percent)+
  labs(x="",y="CTR") +
  theme_grey(20)

prop.test(dat2$CTs,dat2$IMP)

多重比較の話

A/Bテストとは「AとB、2つのものどうしをくらべます」というテストだった。

「2種類より多いものどうしをくらべます」というときは多変量テストという。

多変量テストというのは統計の言葉ではなくWeb業界の言葉だ。

統計用語ではそういうのは多重比較と呼ぶ。

『部長、その勘はズレてます!』では、「多変量テストを実施し、それぞれの組み合わせで統計学的に有意な結果を得るには、大量のトラフィックが必要となる。」(p.158)と述べ、多変量テストではなく、A/Bテストを繰り返して2つずつ比較していくのが良いと主張する。

ここでかんたんなシミュレーションをやってみる。

Web担当者の某氏は、「『統計学的に有意』にクリックされやすい広告を作ろう」と思って、Web広告を次々作って順番に走らせた。

結果、以下のようなデータがとれた。

IMP CTs
10064 487
10080 520
9997 517
9930 511
10014 505
10047 498
10135 554

f:id:abrahamcow:20150322084119p:plain

一番最初の広告と最後の広告で、

  • 帰無仮説:最初の広告のCTR ≧ 最後の広告のCTR
  • 対立仮説:最初の広告のCTR < 最後の広告のCTR

で母比率の差の検定をやった結果、p-値は0.02363、5%水準で有意になった。

dat <-
  structure(list(IMP = c(10064L, 10080L, 9997L, 9930L, 10014L,10047L, 10135L),
                 CTs = c(487L, 520L, 517L, 511L, 505L, 498L, 554L)),
            .Names = c("IMP", "CTs"), row.names = c(NA, -7L), class = "data.frame")



#片側検定
prop.test(c(dat$CTs[7],dat$CTs[1]),c(dat$IMP[7],dat$IMP[1]), alternative = "greater")

#グラフ
dat$CTR <- dat$CTs/dat$IMP
plot(dat$CTR*100,pch=16,type="b",ylim=c(0,6),ylab="CTR(%)")

いろいろ試した結果、7回目にして有意差が出ました。良かった。

……というのはまちがい。

サイコロ投げを例にとろう。

サイコロを一回投げて一の目が出る確率は1/6、約16.7%。一発で一の目がでたらラッキーだ。

でもサイコロを何回も振りなおしたらどうだろう。

サイコロを4回投げて少なくとも一回一の目がでる確率は  1- (5/6)^4、約51.8%。一の目がでないほうがめずらしい。

めずらしい事象も何回も繰り返したら発生する。

p-値(有意確率)が5%以下、というのはめずらしい事象だけど、何回も繰り返したらめずらしくなくなる。

だから仮説検定では多重比較を考慮してやる必要がある。

一番単純な多重比較法はボンフェローニの補正というやつだ。

ボンフェローニの補正では、検定を繰り返した回数をp-値にかけてやる。

今回は7個の中から2つ選んで検定をやったので、 _7C_2=21 をかける。

> prop.test(c(dat$CTs[7],dat$CTs[1]),c(dat$IMP[7],dat$IMP[1]))$p.value*choose(7,2)
[1] 0.992391

p-値は約0.99、ぜんぜん有意じゃない。

A/Bテストを何度も繰り返して、無理やり「有意差」を引っ張りだすのは意味がない。

ちなみに、Rではpairwise.prop.testという関数でかんたんに多重比較の検定ができる。

> pairwise.prop.test(dat$CTs, dat$IMP, p.adjust.method ="bonferroni")

	Pairwise comparisons using Pairwise comparison of proportions 

data:  dat$CTs out of dat$IMP 

  1    2    3    4    5    6   
2 1.00 -    -    -    -    -   
3 1.00 1.00 -    -    -    -   
4 1.00 1.00 1.00 -    -    -   
5 1.00 1.00 1.00 1.00 -    -   
6 1.00 1.00 1.00 1.00 1.00 -   
7 0.99 1.00 1.00 1.00 1.00 1.00

P value adjustment method: bonferroni 

実は、上述のデータは乱数を使ったシミュレーションで作った。シミュレーションで仮定した真のCTRは全部5%。

真のCTRが一緒でも何度も繰り返したらいつかは「有意」になる。

ABsimurator <- function(){
  IMP <- sapply(1:1000, function(i)rpois(1,10000)) #ポアソン到着
  CTs <- sapply(1:1000, function(i)rbinom(1,size=IMP[1],prob=0.05)) #CTR5%
  pval <- numeric()
  for(i in 1:999){
    pval[i] <- prop.test(c(CTs[i+1], CTs[1]), c(IMP[i+1],IMP[1]), alternative = "greater")$p.value
#片側検定でp-値が5%以下になったところを出力
  }
  len <-which.max(pval<0.05)
  data.frame(IMP=IMP[1:(len+1)],CTs=CTs[1:(len+1)])
}
ABsimurator()

では、どうしたらいいか

ここからはぼくの意見です。

『部長、その勘はズレてます!』は「統計的に有意」にすることが自己目的化していると感じた。

それに対して、真面目に統計学を勉強した人なら「多重比較を考慮して、例数設計もやって、きちんと実験計画的にA/Bテストをやろう」と言うかもしれない。

でも、ぼくはそんなの無理だし、意味がないと思う。

A/Bテストに関しては、仮説検定とかやらなくていいと思う。

WebサイトやWeb広告というのは「運用」していくものだ。

ずっと同じサイト、同じ広告ということはありえない。

だからほとんど常にインフレーション的な多重比較になる。

また、有意差が出ない、毒にも薬にもならない施策を打ったって、特別問題が起こるとは思えない。

毒や薬の臨床試験だったら仮説検定は必要だ。

効果のない薬を売ったら詐欺だ。

でもWebページやWeb広告の改善だったら、ちょっとでも良さそうな施策があったら試行錯誤的にそれをやってみればいい。

で、いろいろな施策を打った結果、サイト全体としてのKPIが改善されているかを観察して、また新たな施策を試したらいいと思う。

本ブログ内のA/Bテスト関連の文章(A/Bテスト カテゴリーの記事一覧 - 廿TT)はほとんどずっとこの主張を繰り返している。

参考文献

部長、その勘はズレてます!  「A/Bテスト」最強のウェブマーケティングツールで会社の意思決定が変わる

部長、その勘はズレてます! 「A/Bテスト」最強のウェブマーケティングツールで会社の意思決定が変わる

あと、本エントリで直接参照したわけじゃないけどKPI設計とかサイト改善の参考になりそうな本として、『エンジニアのためのデータ可視化[実践]入門』を挙げておく。

エンジニアのための データ可視化[実践]入門 ~D3.jsによるWebの可視化 (Software Design plus)

エンジニアのための データ可視化[実践]入門 ~D3.jsによるWebの可視化 (Software Design plus)

「エンジニアのための」と銘打たれているけど、JavaScriptのコードの部分は読み飛ばしてもかまわない。

「そもそもなにを可視化すべきか」「どういう可視化をしたらいいか」の事例集として有益だと思う。