最近「効果検証」というキーワードを見聞きする機会が増えてきたので、僕のこれまでの経験に基づいてちろっと書いてみます。
シンプルにA/Bテストをやる場合
色々なところで既に言われていますが、独立性の検定*1一択でしょう。そもそも独立性の検定って、古典的な統計学の世界では
- 予防接種が効いたor効かなかった
- 工場のある工程への改善が効果があったorなかった
といったテストに使われる手法なんですよね。これはどこからどう見てもその当時のA/Bテストそのものです。単にwebで全自動でできるかできないかぐらいの違いしかないです。
ということで、例えばこういう例を考えてみましょう*2。
CVしなかった | CVした | CVR | |
---|---|---|---|
施策打つ前 | 2892 | 447 | 13.3% |
施策打った後 | 2422 | 439 | 15.3% |
物凄くボリューム感が小さいんですが(笑)、そこは置いといて。さて、これは効果があったと言えるんでしょうか?
独立性の検定って、数式さえ覚えていればExcelでもできるんですが、RやSPSSなどでやった方が圧倒的に手っ取り早いです。Rなら以下のような感じでいけます。
> x<-matrix(c(2892,447,2422,439),ncol=2,byrow=T) # データ入力 > chisq.test(x) # カイ二乗検定 Pearson's Chi-squared test with Yates' continuity correction data: x X-squared = 4.6596, df = 1, p-value = 0.03088 # 有意差あり(施策の効果あり) > fisher.test(x) # フィッシャーの正確確率検定 Fisher's Exact Test for Count Data data: x p-value = 0.02899 # 有意差あり(施策の効果あり) alternative hypothesis: true odds ratio is not equal to 1 95 percent confidence interval: 1.014403 1.355613 sample estimates: odds ratio 1.172651
ということで、このケースでは「改善施策の効果あり」という結論になりました。勿論、何が何でも統計学的に正確でなければいけない!ってことはないんですが*3、一つのキーポイントになるのは間違いないと思います。
テレビCMのGRPなど施策のボリュームが定量的に表せる場合
色々やり方はあるんでしょうが、僕はGRPの時系列とKPIの時系列とを合わせてVARモデルにして、その因果性を調べるというやり方をしていました。
> x1<-matrix(rep(0.5,30)) > x2<-matrix(rep(1,30)) > x3<-matrix(rep(0.3,30)) > x<-rbind(x1,x2,x3) > x<-ts(x) # GRPの時系列のつもり > y1<-matrix(rnorm(32)+5) > y2<-matrix(rnorm(30)+7.5) > y3<-matrix(rnorm(28)+2.5) > y<-rbind(y1,y2,y3) > y<-ts(y) # KPIの時系列のつもり > z<-cbind(x,y) # 2つの時系列を合わせる
上のxがGRP、yが何がしかのKPIということにしましょう。一般にGRPは事前に数週間or数ヶ月先まで計画されているものなので、予め取得することが可能な数値データと見て良いと思います。
そこで、これらを表現するVARモデルを推定し、これに基づいて両者の因果関係をチェックしてみましょう。
> VARselect(z) # VARモデルの次数を推定する $selection AIC(n) HQ(n) SC(n) FPE(n) 2 1 1 2 # AICによればp = 2が最適らしい $criteria 1 2 3 4 5 AIC(n) -4.44412676 -4.4618461 -4.44926151 -4.40074093 -4.36952182 HQ(n) -4.37250006 -4.3424683 -4.28213255 -4.18586083 -4.10689060 SC(n) -4.26547476 -4.1640928 -4.03240685 -3.86478493 -3.71446450 FPE(n) 0.01174819 0.0115448 0.01169769 0.01229174 0.01270175 6 7 8 9 10 AIC(n) -4.34575727 -4.29779199 -4.21675912 -4.13121919 -4.18302645 HQ(n) -4.03537492 -3.93965850 -3.81087449 -3.67758344 -3.68163956 SC(n) -3.57159862 -3.40453200 -3.20439780 -2.99975654 -2.93246247 FPE(n) 0.01303726 0.01372121 0.01494159 0.01636309 0.01564099 > z.var<-VAR(z,p=2) # VARモデルを推定する > causality(z.var) # Granger因果性を検定する $Granger Granger causality H0: x do not Granger-cause y data: VAR object z.var F-Test = 16.292, df1 = 2, df2 = 166, p-value = 3.464e-07 # x⇒yなる有意な因果関係がある $Instant H0: No instantaneous causality between: x and y data: VAR object z.var Chi-squared = 0.3957, df = 1, p-value = 0.5293 # x⇔yなる相互影響はない > z.irf<-irf(z.var,n.ahead=15,ci=0.95) # 向こう15期までのインパルス応答関数を推定する > plot(z.irf)
Granger因果性検定では、x⇒yなる因果関係があるという結論になっています。
またインパルス応答関数を見ると、x(GRP)に1標準偏差の分だけ変動を与えるとy(KPI)にショックが伝わって、遅延つきのインパルス応答が生じているのが分かります。すなわち、x⇒yなる因果関係がある!ということですね。ちなみにこれを逆にするとこういう遅延つきのインパルス応答は見られないので、逆は成り立たないという結論になります。
ともあれこれで、「GRPが変動した分だけKPIにもその変動が伝わる ⇒ CMの効果がKPIに表れている」ということが(間接的ながら)言えるわけです。
また、GRPは未来の値まで事前に分かっているケースが多いので、今回求めたインパルス応答関数を用いてKPIの予測値を出すことも出来ます。
なお、VARモデルなのでお決まりの「見せかけの回帰」「共和分」の問題に注意が必要です*4。お忘れなく。
特定の導線設定などユニークユーザーベースで施策を行う場合
この場合はもう仕方ないので、「その導線をたどったか否か」でユーザー行動データそのものを分けて抽出し、それに対して色々分析をやっていくしかないです。つまり、DBから抜いてくる時点でその辺の条件分岐をかけていく必要があります。
つまり、Hadoop + Hiveなんかだと延々と"JOIN"文 vs. "LEFT OUTER JOIN ... WHERE a IS NULL"文みたいなのを繰り返すことになるわけで、はっきり言ってダルいです。個人的にはかったるくて仕方ないので、対象となる範囲に絞って生テーブルをローカルのMySQLとかに落として、そこから抽出した方が得策だろうと思ってます。
抽出してきたデータの分析方法は何でも良いと思いますが、きちんと「施策を打つ前vs.後」という構図に持ち込む必要があります。というか、そうでなければ効果検証になんてなりませんので。。。
そもそも「効果検証」って意味あるの?
以前の記事(「毎日の数字を追いかけ、毎日改善する」ことの意外な落とし穴)でグサグサ刺した通り、結局あたふた焦って「毎日カイゼン毎日効果検証」なんてしていたら意味がないわけです。
大事なことはどういう方法を使うかではなくて、どれくらい大局的かつ明確なトレンドをしっかり捕まえ、それが自分たちの放った改善施策とどう関係しているか?をきちんとロジカルに考えることだと、僕は思ってます。