Abstract
効果検証入門第1章セレクションバイアスとRCTについてまとめたものですビジネス上のなんらかのアクション(広告展開, セールなど)を実施した際に売り上げなどのKPIに与えた影響を効果と呼び, そのアクションのことを介入と呼ぶ
介入(本書ではメールマーケ)をしなくても観測される売上を潜在的な購買量と呼ぶ
介入はコストの問題から限られた人数に実施されるが, シンプルに対象者と非対象者を比較するだけでは問題が発生する
効率性の観点から, メール配信をする際にはある程度購買見込みのある顧客が対象となることが多いが, 以下の問題が発生する
メール対象者はそもそもの購買量が大きいので, 非対象者と購買量に大きく差がつく
非対象者は潜在的な購買量が少ない
このように得られた結果と本当の効果の乖離をセレクションバイアスと呼ぶ
介入を無作為に決めることが信頼のおける検証方法である→RCT(無作為化比較実験, Randomized Controlled Trial)
介入効果については以下のようにあらわせる. \[Z_i = \left\{ \begin{array}{ll} 1 & (メールが配信された場合) \\ 0 & (メールが配信されなかった場合) \end{array} \right.\]
また, 売上Yに関しては以下のように場合分けできる. \[Y_i = \left\{ \begin{array}{ll} Y^{(1)}_i & (Z_i = 1) \\ Y^{(0)}_i & (Z_i = 0) \end{array} \right.\]
この売上の差に介入の本当の効果があると考えることをポテンシャルアウトカムフレームと呼ぶ
売上Yはどちらかしか観測されないので, 観測されない側の結果をポテンシャルアウトカムという
この表ではメールの効果が全てのユーザで等しく100となっている
i | Y | \(Y^{0}\) | \(Y^{1}\) | Z |
---|---|---|---|---|
1 | 300 | 300 | 400 | 0 |
2 | 600 | 500 | 600 | 1 |
3 | 600 | 500 | 600 | 1 |
4 | 300 | 300 | 400 | 0 |
5 | 300 | 300 | 400 | 0 |
6 | 600 | 500 | 600 | 1 |
7 | 600 | 500 | 600 | 1 |
8 | 300 | 300 | 400 | 0 |
9 | 600 | 500 | 600 | 1 |
10 | 300 | 300 | 400 | 0 |
このデータにおいて介入の効果\(\tau\)は以下の式であらわせる. \[\tau = Y^{1} - Y^{0}\]
介入効果\(\tau\)は期待値の差であらわせる. \[\tau = E[Y^{1}] - E[Y^{0}]\]
介入ありのユーザの平均売上は600, 介入なしのユーザの平均売上は300となるため, メールによって増加した売上は\(600 - 300 = 300\)となるが, すべてのサンプルで\(Y^{1} - Y^{0} = 100\)となっているので, 効果を過剰に見積もっていることになる
このグループ間の比較は以下のような条件付き期待値を推定していることになる\[\tau_{naive} = E[Y^{1}|Z=1] - E[Y^{0}|Z=0]\]
セレクションバイアスとは, メール配信対象のユーザと, 配信対象にならないユーザにおける, メールを受け取らないときの売上の違い
メール配信対象者はランダムに決定されるため, 潜在的な売上の期待値は0になる \[E[Y0|Z=1] - E[Y0|Z=1] = 0\]
ランダムに割り振ったデータ. 平均値の差は\(500-400=100\)となる. よってセレクションバイアスは0である
i | Y | \(Y^{0}\) | \(Y^{1}\) | Z |
---|---|---|---|---|
1 | 300 | 300 | 400 | 0 |
2 | 600 | 500 | 600 | 1 |
3 | 600 | 500 | 600 | 0 |
4 | 300 | 300 | 400 | 1 |
5 | 300 | 300 | 400 | 0 |
6 | 600 | 500 | 600 | 0 |
7 | 600 | 500 | 600 | 1 |
8 | 300 | 300 | 400 | 1 |
9 | 600 | 500 | 600 | 0 |
10 | 300 | 300 | 400 | 0 |
有意差検定(t検定)を行う
有意水準が5%以下であれば, 平均の差が0である可能性は低いと考えられる
5%より大きければ平均の差が0であることを否定できない
ただし, 検定結果がセレクションバイアスの影響を受けることもあるので必ずしも効果を保証するとは限らない
メールマーケティングの効果を実際のデータセットを用いて分析する.
ECサイトのユーザに対してランダムに男性向け, 女性向け, メールを送らない, の3パターンが適用される.
今回は女性向けは削除し, 男性向けメール配信対象サンプルとメールが配信されなかったサンプルで売り上げに差があるのかを調べる.
# ライブラリの読み込み
library(tidyverse)
## ─ Attaching packages ──────────────────── tidyverse 1.3.0 ─
## ✓ ggplot2 3.3.3 ✓ purrr 0.3.4
## ✓ tibble 3.0.6 ✓ dplyr 1.0.4
## ✓ tidyr 1.1.2 ✓ stringr 1.4.0
## ✓ readr 1.4.0 ✓ forcats 0.5.1
## ─ Conflicts ───────────────────── tidyverse_conflicts() ─
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
#データのダウンロード
email_data <- read_csv("http://www.minethatdata.com/Kevin_Hillstrom_MineThatData_E-MailAnalytics_DataMiningChallenge_2008.03.20.csv")
##
## ─ Column specification ────────────────────────────
## cols(
## recency = col_double(),
## history_segment = col_character(),
## history = col_double(),
## mens = col_double(),
## womens = col_double(),
## zip_code = col_character(),
## newbie = col_double(),
## channel = col_character(),
## segment = col_character(),
## visit = col_double(),
## conversion = col_double(),
## spend = col_double()
## )
#データの確認
head(email_data)
## # A tibble: 6 x 12
## recency history_segment history mens womens zip_code newbie channel segment
## <dbl> <chr> <dbl> <dbl> <dbl> <chr> <dbl> <chr> <chr>
## 1 10 2) $100 - $200 142. 1 0 Surburb… 0 Phone Womens…
## 2 6 3) $200 - $350 329. 1 1 Rural 1 Web No E-M…
## 3 7 2) $100 - $200 181. 0 1 Surburb… 1 Web Womens…
## 4 9 5) $500 - $750 676. 1 0 Rural 1 Web Mens E…
## 5 2 1) $0 - $100 45.3 1 0 Urban 0 Web Womens…
## 6 6 2) $100 - $200 135. 0 1 Surburb… 0 Phone Womens…
## # … with 3 more variables: visit <dbl>, conversion <dbl>, spend <dbl>
データのダウンロードができたので, 女性向けメール配信サンプルを削除する.
「segment」列にどのメールが配信されたかの情報が入っており, さらにダミー変数に変換する.
male_df <- email_data %>%
#女性向けメール配信者を除外
filter(segment != "Womens E-Mail") %>%
#ダミー変数に変換
mutate(treatment = if_else(segment == "Mens E-Mail", 1, 0))
次にトリートメントありかなしかで集計を行う.
conversion_rateはメール配信後2週間以内に購入したかの確率, spend_meanは購入額の平均となっている.
countについてはそれぞれのサンプル数である.
summary_by_segment <- male_df %>%
#グルーピング
group_by(treatment) %>%
summarise(conversion_rate = mean(conversion),
spend_mean = mean(spend),
count = n())
summary_by_segment
## # A tibble: 2 x 4
## treatment conversion_rate spend_mean count
## * <dbl> <dbl> <dbl> <int>
## 1 0 0.00573 0.653 21306
## 2 1 0.0125 1.42 21307
結果を確認するとメールありの購入確率が1.25%, なしの購入確率が0.57%となっており, それに伴って平均購入額もメールありのほうが0.767程度大きい.
このデータに関してはランダムにメールが配信されているため, セレクションバイアスはないと考えられる.
この結果に対してt検定を行い, 有意差があるかを確認する.
#メール受信者の消費額を抽出
mens_email <- male_df %>%
filter(treatment == 1) %>%
#列の抽出に関してはselect()が一般的だがpull()でも可能
#pullの場合リストで抽出される
pull(spend)
#メール未受信者の消費額を抽出
no_mail <- male_df %>%
filter(treatment == 0) %>%
pull(spend)
#t検定
rct_ttest <- t.test(mens_email, no_mail, var.equal = TRUE)
rct_ttest
##
## Two Sample t-test
##
## data: mens_email and no_mail
## t = 5.3001, df = 42611, p-value = 1.163e-07
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## 0.4851384 1.0545160
## sample estimates:
## mean of x mean of y
## 1.4226165 0.6527894
p値は0.05未満であり, 検定の結果からは平均の差は0ではない可能性が高く, 有意差があると考えられる.
購買傾向が一定以上あるユーザに対して意図的にメール配信をした状況で分析する.
historyは昨年度の購買金額を表しており, 金額が一定以下のデータはランダムに5割削除し,
さらにメールを配信しない.
したがって, メール配信者の平均購買額は大きくなると予想される.
set.seed(1)
#条件に反応するサンプル量を半分にする
obs_rate_c <- 0.5
obs_rate_t <- 0.5
#バイアスデータの作成
biased_data <- male_df %>%
#コントロール群
#購買傾向が低いサンプルに1を与える
mutate(obs_rate_c = if_else((history > 300) | (recency < 6) |
(channel == "Multichannel"), obs_rate_c, 1),
#トリートメント群
#購買傾向が高いサンプルに1を与える
obs_rate_t = if_else((history > 300) | (recency < 6) |
(channel == "Multichannel"), 1, obs_rate_t),
#乱数発生
random_number = runif(n = NROW(male_df))) %>%
#メール未配信かつ発生させた乱数が0.5未満のコントロール群を半分抽出
filter((treatment == 0 & random_number < obs_rate_c)|
#メール配信かつ発生させた乱数が0.5未満のトリートメント群を半分抽出
(treatment == 1 & random_number < obs_rate_t))
summary_by_segment_biases <- biased_data %>%
group_by(treatment) %>%
summarise(conversion_rate = mean(conversion),
spend_mean = mean(spend),
count = n())
summary_by_segment_biases
## # A tibble: 2 x 4
## treatment conversion_rate spend_mean count
## * <dbl> <dbl> <dbl> <int>
## 1 0 0.00498 0.548 14665
## 2 1 0.0134 1.53 17198
売り上げ発生確率の差は0.00842, 平均購買額の平均の差は0.982となっており, RCTの時よりさらに大きくなっている
#メール受信者の抽出
mens_mail_biased <- biased_data %>%
filter(treatment == 1) %>%
pull(spend)
#メール未受信者の抽出
no_mail_biased <- biased_data %>%
filter(treatment == 0) %>%
pull(spend)
#t検定
rct_ttest_biased <- t.test(mens_mail_biased, no_mail_biased, var.equal = T)
rct_ttest_biased
##
## Two Sample t-test
##
## data: mens_mail_biased and no_mail_biased
## t = 5.6708, df = 31861, p-value = 1.433e-08
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## 0.6409145 1.3179784
## sample estimates:
## mean of x mean of y
## 1.5277526 0.5483062
t検定の結果, 平均の差はさらに広がり, p値も小さくなったがこれによって特に分析の質が改善したというわけではない.
つまり統計的有意差があるからといって結果を鵜呑みにしてはいけない.
実社会でRCTを実行するにはさまざまな障壁がある.
ユーザをランダムに選択するため, 一時的に売り上げが減少してしまう可能性がある
何らかの施策や法律をランダムに割り振ることはコストだけでなく, 倫理的に問題がある
ユーザによって提示する金額が違うと炎上のリスクがある
このように理想的にはRCTで分析したいが不可能に近いという状態である.
セレクションバイアスは人為的な介入によって発生する. 何故なら介入を選択する人が利得を高めようとした結果が現れているからである
PDCAサイクルを回す際にバイアスのループに陥る可能性がある
メール配信の例では1回目に各年代にメールを配信し, 次に効果が良さそうな世代にメールを配信して効果を高めようとするが, ここには年代によるセレクションバイアスが含まれる
例えば, 元々若者が多く購買しているものであれば, 若年層への効果が高いと見えてしまう
これが繰り返されるとコストもかさみ, 過剰評価にも繋がるため, KPIの改善にならない
結果的にセレクションバイアスが大きくなり, 改善の知見は見せかけのものになってしまう