Quantcast
Channel: blog - ブログ - 株式会社JADE
Viewing all articles
Browse latest Browse all 107

素人でも1ヶ月 Causal Impact で遊んだら、統計的有意差が見えるようになった話

$
0
0

こんにちは。2024年5月にJADEに入社した江越です。

前職でデータ加工を生業としていた関係で、現在はデータ分析に関わるサポートをメインに取り組んでいます。……とはいえ、法学部出身ということもあり、統計やデータ分析に関しては「素人に毛が生えた程度」の知識しかありません。

今回は、そんな統計素人の私が Causal Impact という分析パッケージに1ヶ月間触れてみた結果、施策の効果を統計的かつ定量的に説明できる手段が得られた経験をシェアしたいと思います。

【もくじ】

Causal Impactとの出会い

統計素人の私が Causal Impact と出会ったきっかけは、端的に言えば弊社が開催したウェビナーでした。

※弊社では継続的に学び合うための勉強会があり、その中で自社が登壇したセミナーを振り返るカリキュラムがあります。素敵ですよね。

そのウェビナーで「Causal Impact」という聞き慣れないワードを耳にした当時の私。「どうやら簡単なプログラミング実装で統計的に施策の効果検証ができる代物らしいけれど、それ以上のことは分からんな〜」とモヤモヤしていました。曖昧な理解を放っておけない性分の私は、気になるあの子のことを想うように、Causal Impact のことを考えて眠れない夜が続きました。

……という冗談はさておき、やはり気になるものは気になるものです。加えて、個人的に効果検証の手法について行き詰まりを感じていた部分もあり、試しに Causal Impact を使ってみることにしました。

(実はウェビナーのアーカイブ公開しております……!よろしければどうぞ!)

ja.dev

効果検証について持っていた課題感

Causal Impact を知る前の効果検証手段

Causal Impact を学ぶ前、私が抱えていた課題は「統計的有意差を定量的に示す」手段を効果検証に用いていなかったことでした。

※統計的有意差がある:「偶然生じうる誤差の範囲を超えて差がある」状態を指します。

では、当時の私が効果検証を求められたら、どのような説明をしていたのでしょうか。大まかには以下のようなものでした。

「施策後の数値から施策前の数値を引いたところ、これだけの差分が生じました。経験則から言えば、この程度の差分があれば施策に効果があったと判断できると思います。」

上記の説明の何が問題なのか?

「え、上記の説明で十分じゃないの?」と思われる方もいらっしゃるでしょう。確かに、意思決定がスムーズに進み、施策が順調に展開され効果を発揮できるなら、結果的には問題ないかもしれません。

しかし、大規模な予算や工数を投じる施策の場合、以下のような観点からの説明も求められることがあるのではないでしょうか?

  • 施策の前後に生じた差分が、単なる偶然の誤差ではないことを確認したい
  • 誤差の可能性を考慮した上で、実際のインパクトがどの程度あったのかを知りたい
  • 可能であれば、季節変動による差分を除外し、施策の純粋な効果を定量的に把握したい

せっかく予算を投じて施策を実行したのに、「あの時の効果は単なる偶然でした。申し訳ありません」では、あまりにもったいないですよね。

さらに、各施策がもたらす影響をより正確に把握し、それぞれにどれだけのリソースを割り当てるべきか判断したいケースも少なくありません。

これらの要求に応えるには、単純な差分を示すだけでは不十分で「統計的な有意差を定量的に示す」必要があります。かといって統計学やプログラミングをしっかり学んだ経験がなかった自分は、最適な手段を持ち合わせているわけもありませんでした。

こんな状況で出会ったのが Causal Impact であり、もしかすると自分の課題感を解決する鍵になるかも?と思い立った私は、この未知のパッケージとの戯れに身を投じてみることにしました。

google.github.io

実際に遊んでみる

Causal Impactとは一体何者だ!

さて、遊んでみよう!といっても Causal Impact が何者かもよく知らない私。とりあえずGoogle検索を活用して以下の情報を得ました。

  • Causal Impact はGoogleが作ったRパッケージ。Pythonでも利用できるらしい
  • 施策を行う前のデータを学習して、施策が行われなかった場合のデータがどうなるかを予測してくれる。予測値と実測値を比べれば施策に効果があったかを調べられる
  • 予測に必要な種データは「時系列」と「実測値」、必要に応じて「共変量」の最大3種類

何をすれば良いか整理してみる

これで Causal Impact の概念の大枠は掴めましたが、具体的な手順はまだ把握できていません。

差し当たり「PythonかRを使う必要があるんだな」ということは分かったので、プログラミングの基本である「input/through/output」の枠組みで流れを整理してみました。

  • input:時系列データ、実測値、および必要に応じて、共変量を含むデータセットの準備をする
  • through:Pythonでinputデータを Causal Impact に渡し、予測を実行する
  • output:予測値と実測値の差分を算出し、結果を表示する

inputとthroughを用意して実行してみる

大まかに必要な情報が整理できたので、実験の準備です。

前提情報として以下のような状況を想定して、データとコードを準備してみました。

 

前提情報

  • テスト概要
    • テスト対象:月曜火曜にトレンドのある動きを見せるクエリ×URL群
    • 改善施策:2020年2月1日にタイトル改善をリリースした
  • データ概要
    • 期間:(前)2020-01-01 - 2020-01-31、(後)2020-02-01 - 2020-02-28
    • metric(実測値):Click数
    • covariate(共変量):Impression数

 

Inputデータ(Googleスプレッドシート)

dateClickImpression
2020-01-01735248804
2020-01-02732341160
2020-01-03413619420
2020-01-04417020433
2020-01-05442321604
2020-01-06403124975
2020-01-07409620966
2020-01-08730843164
2020-01-09719343956
2020-01-10413020643
2020-01-11409019420
2020-01-12416419800
2020-01-13412421582
2020-01-14431020895
2020-01-15746439160
2020-01-16742339984
2020-01-17424520958
2020-01-18409819280
2020-01-19401121230
2020-01-20406423088
2020-01-21428319820
2020-01-22740440344
2020-01-23748041706
2020-01-24421121956
2020-01-25429123568
2020-01-26449423000
2020-01-27448919740
2020-01-28405419280
2020-01-29743147760
2020-01-30738046201
2020-01-31436024575
2020-02-01588720307
2020-02-02562820958
2020-02-03529621626
2020-02-04512420286
2020-02-05794338320
2020-02-06763542828
2020-02-07669222770
2020-02-08673324525
2020-02-09655123280
2020-02-10693221850
2020-02-11653220181
2020-02-12983839160
2020-02-13975640098
2020-02-14623122471
2020-02-15645120118
2020-02-16648820265
2020-02-17690823280
2020-02-18657321340
2020-02-19957246320
2020-02-20939545073
2020-02-21638722954
2020-02-22602322824
2020-02-23658922333
2020-02-24621320988
2020-02-25622019940
2020-02-26921447383

 

コード(Google Colab)

#######0-事前準備# 必要なライブラリ、パッケージを用意

!pip install gspread pandas
!pip install tfcausalimpact

import gspread
import pandas as pd

from causalimpact import CausalImpact
from google.colab import auth
from google.auth import default


# 認証などを行います

auth.authenticate_user()
creds, _ = default()
gc = gspread.authorize(creds)



#######1-input# スプレッドシートにアクセスします

ss_url = "https://docs.google.com/spreadsheets/hogehoge"#対象のスプレッドシートのURLを突っ込む
spreadsheet = gc.open_by_url(ss_url)

# 最初のシートを取得します

sheets = spreadsheet.sheet1

# シートごとのデータを格納するリストを作成します

all_data = []

# 最初のシートのデータを取得し、データフレームに追加します

data = sheets.get_all_values()
input_df = pd.DataFrame(data[1:], columns=data[0])

# 結果変数と共変量のカラムを数値型に変換(ここは小数型に)

input_df['Click']=input_df['Click'].astype(float)
input_df['Impression']=input_df['Impression'].astype(float)

# 時系列カラムをindexに指定

input_df.set_index('date',inplace=True)

#データ型が変換できているか確認print(input_df.dtypes)



#######2-through# 期間設定

pre_period = ['2020-01-01', '2020-01-31']
post_period = ['2020-02-01', '2020-02-26']

# 実行

impact = CausalImpact(input_df, pre_period, post_period)




#######3-output# 結果の確認print(impact.summary())
print(impact.summary(output='report'))
impact.plot()

統計的有意差が見える……見えるぞっ!

Causal Impact を実行した結果

上記で準備したコードを実行してみると、以下のようなレポートとグラフが得られました。

 

レポート

> Posterior Inference {Causal Impact}
> Average            Cumulative
> Actual                    7031.19            182811.0
> Prediction (s.d.)         5088.55 (171.67)   132302.41 (4463.33)
> 95% CI                    [4762.14, 5435.06] [123815.75, 141311.68]


> Absolute effect (s.d.)    1942.64 (171.67)   50508.59 (4463.33)
> 95% CI                    [1596.13, 2269.05] [41499.32, 58995.25]

> Relative effect (s.d.)    38.18% (3.37%)     38.18% (3.37%)
> 95% CI                    [31.37%, 44.59%]   [31.37%, 44.59%]

> Posterior tail-area probability p: 0.0
> Posterior prob. of a causal effect: 100.0%

> For more details run the command: print(impact.summary('report'))
> Analysis report {CausalImpact}

> During the post-intervention period, the response variable had
> an average value of approx. 7031.19. By contrast, in the absence of an
> intervention, we would have expected an average response of 5088.55.
> The 95% interval of this counterfactual prediction is [4762.14, 5435.06].
> Subtracting this prediction from the observed response yields
> an estimate of the causal effect the intervention had on the
> response variable. This effect is 1942.64 with a 95% interval of
> [1596.13, 2269.05]. For a discussion of the significance of this effect,
> see below.

> Summing up the individual data points during the post-intervention
> period (which can only sometimes be meaningfully interpreted), the
> response variable had an overall value of 182811.0.
> By contrast, had the intervention not taken place, we would have expected
> a sum of 132302.41. The 95% interval of this prediction is [123815.75, 141311.68].

> The above results are given in terms of absolute numbers. In relative
> terms, the response variable showed an increase of +38.18%. The 95%
> interval of this percentage is [31.37%, 44.59%].

> This means that the positive effect observed during the intervention
> period is statistically significant and unlikely to be due to random
> fluctuations. It should be noted, however, that the question of whether
> this increase also bears substantive significance can only be answered
> by comparing the absolute effect (1942.64) to the original goal
> of the underlying intervention.

> The probability of obtaining this effect by chance is very small
> (Bayesian one-sided tail-area probability p = 0.0).
> This means the causal effect can be considered statistically
> significant.

 

グラフ

得られた結果を解釈してみる

英文が多くて「うっ……」となる方もいらっしゃるかもしれませんが、レポートの内容は意外とシンプルです。上記で得られた結果を簡潔に解釈してみましょう。

レポートの解釈

施策の効果を端的に知りたいなら、最後のパラグラフに注目するとよいでしょう。今回の実験では、以下のような記述があります。

The probability of obtaining this effect by chance is very small
(Bayesian one-sided tail-area probability p = 0.0).
This means the causal effect can be considered statistically
significant.

上記の記述は「偶然に差分が生まれた可能性はとても低く、統計的に有意差があると考えられる」ということを示しています。

 

また、差分が具体的にどの程度あったのかについては、レポート上部にある以下の数表を見ると分かりやすいでしょう。

> Average            Cumulative
> Actual                    7031.19            182811.0
> Prediction (s.d.)         5088.55 (171.67)   132302.41 (4463.33)
> 95% CI                    [4762.14, 5435.06] [123815.75, 141311.68]


> Absolute effect (s.d.)    1942.64 (171.67)   50508.59 (4463.33)
> 95% CI                    [1596.13, 2269.05] [41499.32, 58995.25]

> Relative effect (s.d.)    38.18% (3.37%)     38.18% (3.37%)
> 95% CI                    [31.37%, 44.59%]   [31.37%, 44.59%]
>

数表の構成が少し分かりにくいかもしれませんが、以下のようになっています。

  • 横方向
    • 左側:平均値
    • 右側:累計値
  • 縦方向
    • Actual:実測値
    • Prediction:予測値
    • Absolute effect:実測値と予測値の差(実数)
    • Relative effect:実測値と予測値の差(比率)
    • 95% CI:各指標の95%信頼区間

※信頼区間:誤差を考慮した上で、真の値が含まれる可能性が高い範囲のこと

以上を踏まえて数表から読み解くと、タイトル改善施策の日次効果は実数値ベースで+1,942.64Click(95%信頼区間:+1,596.13〜+2,269.05Click)、比率で見ると+38.18%(95%信頼区間:+31.37%〜+44.59%)の効果があったと解釈できます。

 

グラフの解釈

グラフは3つあり、それぞれ以下の内容を描画しています。

  • 上段:予測値(点線)と実測値(実線)の比較
  • 中段:実測値と予測値の差分
  • 下段:施策後期間における実測値と予測値の差分の累積

まず一番上のグラフで、Predicted(予測値)とy(実測値)に注目してください。両者の線がかなり重なっていることがお分かりでしょう。これは、ClickとImpressionの共変関係を Causal Impact が学習し、波形を正確に予測できるようになったことを示しています。つまり、Impressionの増加によって生じるClick増加の影響についてはすでに学習済みなので、その影響を除外した形で施策の純粋な効果を把握できるというわけです。

またそれぞれのグラフに描かれているオレンジの範囲は、いわゆる信頼区間を表しています。この信頼区間は、誤差の可能性を考慮した上で取りうる値の範囲を示しています。

例えば一番下のグラフを見ると、期間終了時のオレンジの範囲がおよそ40,000〜60,000の間を示しています。これは誤差を考慮した上で、タイトル改善施策による累積効果として取りうる値の範囲を表しているのです。

ここまでの実験で挙動はなんとなく分かりましたが、Causal Impact の限界についても知りたいのでもう2パターンほど実験してみました。

 

別パターンその1 〈共変量なしで回してみる〉

先ほどの実験したデータから共変量に当たるImpressionカラムを取り除いてみます。共変量を無しにした時、予測値がどうなるかをみてみましょう。

 

Inputデータ(Impressionなし)

dateClick
2020-01-017352
2020-01-027323
2020-01-034136
2020-01-044170
2020-01-054423
2020-01-064031
2020-01-074096
2020-01-087308
2020-01-097193
2020-01-104130
2020-01-114090
2020-01-124164
2020-01-134124
2020-01-144310
2020-01-157464
2020-01-167423
2020-01-174245
2020-01-184098
2020-01-194011
2020-01-204064
2020-01-214283
2020-01-227404
2020-01-237480
2020-01-244211
2020-01-254291
2020-01-264494
2020-01-274489
2020-01-284054
2020-01-297431
2020-01-307380
2020-01-314360
2020-02-015887
2020-02-025628
2020-02-035296
2020-02-045124
2020-02-057943
2020-02-067635
2020-02-076692
2020-02-086733
2020-02-096551
2020-02-106932
2020-02-116532
2020-02-129838
2020-02-139756
2020-02-146231
2020-02-156451
2020-02-166488
2020-02-176908
2020-02-186573
2020-02-199572
2020-02-209395
2020-02-216387
2020-02-226023
2020-02-236589
2020-02-246213
2020-02-256220
2020-02-269214

 

Outputグラフ(Impressionなし)

 

一番上のグラフを見ていただくと、学習用データとして与えた前期間の予測値(Predicted)が実際の値(y)から大きく乖離してしまっていることがお分かりいただけると思います。変動の少ないデータであれば共変量を設定しなくても精度の高い予測が可能ですが、今回のように一定以上の変動が存在するデータについては、適切な共変量を設定した方が予測精度が向上しそうです。

共変量の例としては、最初の実験のように実測値に影響を与える指標(例:Clickに対するImpression)を設定するパターンのほか、テスト以外の条件・傾向が揃っている非テスト群の実測値を入れてみるパターンなどが考えられます。どの共変量を設定すれば予測が正確になるかは状況によって様々です。そのため、データと実験対象の特性を考慮しながら、試行錯誤してみるのがよいでしょう。

 

別パターンその2 〈規則性のないデータを元にAAテストを回してみる〉

また、学習が困難なデータの扱いにも課題があるのではないかと考えました。そこで、何の施策も実施していないという前提で入力データを用意し、Causal Impact を適用してみることにしました(いわゆるAAテスト)。

 

Inputデータ(不規則な変化)

dateClickImpression
2020-01-01593749427
2020-01-02537640764
2020-01-03983618395
2020-01-04487638858
2020-01-05293717133
2020-01-062044314058
2020-01-07945446000
2020-01-08607430951
2020-01-09937236974
2020-01-10324910778
2020-01-11705924643
2020-01-121893232762
2020-01-13320135758
2020-01-14345442654
2020-01-15564215379
2020-01-16497344152
2020-01-17826927102
2020-01-18722247742
2020-01-191633715665
2020-01-20917820444
2020-01-21109025416
2020-01-22438114568
2020-01-23910728640
2020-01-24369032918
2020-01-25837323165
2020-01-26546824005
2020-01-27629615991
2020-01-28169248932
2020-01-29545434796
2020-01-30348329899
2020-01-31413035383
2020-02-01288110478
2020-02-02187422467
2020-02-0392314103
2020-02-0487313304
2020-02-05193247672
2020-02-06202216744
2020-02-07334522346
2020-02-08315520359
2020-02-09414717610
2020-02-10729849650
2020-02-11126034437
2020-02-12429838343
2020-02-13353429264
2020-02-14455428002
2020-02-15839845654
2020-02-16158137156
2020-02-17357541462
2020-02-181028331711
2020-02-19348615716
2020-02-20323834430
2020-02-21385343767
2020-02-22266044705
2020-02-23372037555
2020-02-24242511900
2020-02-25703228964
2020-02-261563915444

 

Outputグラフ(不規則な変化)

 

上記の例では施策を実施していないにもかかわらず、後期間で統計的な有意差が確認されてしまっています。共変量としてImpressionを設定したものの、Clickの増減との関連性が特に見られないため、予測が正確に成り立っていません。このような状況下では施策の効果を検証しようとしても、それが施策の効果なのか、それとも偶然によるものなのか、判断が困難になってしまいます。

精度を向上させる試みとして、テスト群の再選定やデータクレンジング、他の共変量の検討といった可能性が考えられます。しかし、常に適切な解決策が見つかるとは限りません。このように Causal Impact が不向きなケースが存在することを認識しておくことも重要だと考えています。

 

ここまで Causal Impact を使って、その可能性を実験ベースで探ってきました。

Causal Impact の特徴を3点でまとめるなら、以下の感じかなと。

  • 値を予測する際、信頼区間を算出してくれるので、誤差を定量的に把握できる
  • 共変量をうまく設定すれば、他の要因の影響を排除した上で予測できる
  • ただし共変量で説明できない不規則な変化があると予測が困難に

確かに予測が難しいケースも存在しますが、共変量を用いて他要因の影響を排除し、施策の効果を統計的かつ定量的に示せるツールとして、Causal Impact の威力を実感しました。何やかんやで Causal Impact すごい。

 

R・Pythonなんて書けないよ……と思ったそこのあなたへ

「え、なんかしれっとPythonが登場してない……?」

「プログラミングなんて書けないよ……」

安心してください。実は私もPythonをまともに触ったことがありません。

ただそんな私でも、LLMやGoogle検索が普及した現代では、仕様さえ詳細に言語化できれば、Causal Impact のような分析をノンプログラマーでも実装し、統計的有意差があるかを語れる時代になりました。改めて振り返ってみても自分の業務の多くは、LLMがなければ手の届かなかったものばかりです。技術の進化に感謝ですね。

最後にそんなノンプログラマーの私が、LLMが登場した現代においてアドホックなプログラムを組む必要が生じた時に意識していることをご紹介し、このブログを締めたいと思います。

  1. プログラミングは人間から機械への依頼であることを強く意識する。
  2. プログラミングの文法よりも、そもそも機械にどんなことができるのかを知る。
  3. 機械ができることを組み合わせたら、どんなものが出来上がるのかイメージできるようになる。
  4. プログラミングの文法については覚えていたらラッキー程度のスタンス。覚えていなかったらLLMやGoogle検索を頼ればよい。

Causal Impact は確かに簡単なプログラミング実装が必要ですが、今は実装を助ける便利な情報やツールが溢れている時代です。使いこなせるようになれば、統計的かつ定量的に効果を検証できる強力な手段となり、心強い味方になることは間違いありません。

まずは遊んでみることから。Causal Impact、皆さんもぜひチャレンジしてみてください!

 

なお実際のSEO施策で Causal Impact を活用した話は、弊社長山執筆の以下ブログに記載があります。こちらもよろしければぜひご覧ください!

blog.ja.dev


Viewing all articles
Browse latest Browse all 107

Trending Articles