見出し画像

ベイジアンABテストの利点と活用例(後編)


ベイジアンABテストはいい結果がでなかったらテスト期間を延長できる

前回では既存のABテストでは有意差があると何%くらい信じて良いかわからないが、ベイジアンABテストだと何%信じて良いかわかるのでより説明性があることを解説した

今回では
ベイジアンABテストのもう一つの利点
「いい結果が出たらいつでもテストを延長できる」
について解説していく


既存のABテストでテストを延長してはダメな理由

1. 多重検定により第1種の過誤を増加させるリスクがある

既存の頻度論的ABテストで有意差が出たときにテスト期間を増やして
仮説検定しなおすということをやってる企業が多いがこれはダメである

なぜならこのケースの場合は
検定統計量が少なくとも1回棄却域に入っていればいいので
その確率は毎回棄却域に入っていない場合の余事象となる

例えば1回目2回目は棄却域に入らずテスト期間を延長して
3回目でようやく棄却域に入った場合は
有意水準を5%とすると

$$
1 - (0.95)^3 = 0.143 
$$

となり有意水準が5%から14.3%になってしまい
当初の精度で仮説検定ができなくなってしまっている

詳しくは下記を参照

2. 結果の再現性が低下し客観確率の定義に反する

サンプルサイズが計画通りに収集されなかった場合、その結果は統計的に安定していない可能性がある

そのため、後から同じ試験を行った場合に同様の結果が得られる保証がなくなって頻度論的統計学で用いられる客観確率の定義に反する

客観確率に関しては松下[1960]を参照

https://www.jstage.jst.go.jp/article/kisoron1954/5/1/5_1_38/_pdf

主観確率と客観確率については下記を参照



ベイジアンABテストでテスト期間延長して良い理由

1. 事後分布の更新新しい確率(事後確率)を更新

ベイジアンアプローチでは、テストデータが新たに得られるたびに事後分布を更新する

事後分布は、事前分布と新しいデータ(尤度)を組み合わせて計算されるため、テストを延長してデータを追加しても、事後分布が単に新しいデータを反映して更新される仕組みである

この過程では、毎回のデータが統合されて新しい信念(事後確率)を形成するため、テスト期間を延長することによって誤った結論が導かれるリスクは低くなる

2. 途中経過のチェックで意思決定しても問題ない

ベイジアンABテストでは、テスト期間中に途中経過をチェックして、事後確率が一定の基準(例えば、あるバージョンが他よりも優れている確率が95%を超えたらテストを終了する)を満たした時点でテストを打ち切ることができる

この方法は、頻度論的なテストで問題となる「ピーキング」(途中で結果を見て判断する)とは異なり、ベイジアンアプローチでは自然な方法として組み込まれている
テストを続けても、事後分布が最新のデータに基づいて更新されるだけなので、テスト期間の延長が結果の信頼性に悪影響を与えることはない


ベイジアンABテストのテスト期間延長 実装例

上の図がテスト期間延長前のABテストで
Aの方が優れている確率が57%であった

データを更新し新しい事後分布を生成したのが下図で
Aの方が優れている確率が100%になった

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import beta

# 事前分布のパラメータ
alpha_prior = 1
beta_prior = 1

# 初期の観測データ(例:A/Bテスト結果)
# Aバージョンの初期データ(僅差に設定)
alpha_A_initial = alpha_prior + 25  # 25回のコンバージョン
beta_A_initial = beta_prior + 75    # 75回の非コンバージョン

# Bバージョンの初期データ(僅差に設定)
alpha_B_initial = alpha_prior + 24  # 24回のコンバージョン
beta_B_initial = beta_prior + 76    # 76回の非コンバージョン

# データを更新
# 追加の観測データ(例:新たな結果)
# Aバージョンでは良い結果(コンバージョン率が高い)
additional_conversions_A = 50
additional_non_conversions_A = 50

# Bバージョンでは悪い結果(コンバージョン率が低い)
additional_conversions_B = 10
additional_non_conversions_B = 90

# 更新後の事後分布のパラメータ
alpha_A_updated = alpha_A_initial + additional_conversions_A
beta_A_updated = beta_A_initial + additional_non_conversions_A

alpha_B_updated = alpha_B_initial + additional_conversions_B
beta_B_updated = beta_B_initial + additional_non_conversions_B

# x軸の範囲(コンバージョンレート)
x = np.linspace(0, 1, 100)

# 事前分布の計算
prior = beta(alpha_prior, beta_prior)

# 初期の事後分布の計算
posterior_A_initial = beta(alpha_A_initial, beta_A_initial)
posterior_B_initial = beta(alpha_B_initial, beta_B_initial)

# 更新後の事後分布の計算
posterior_A_updated = beta(alpha_A_updated, beta_A_updated)
posterior_B_updated = beta(alpha_B_updated, beta_B_updated)

# 確率計算
n_samples = 100000
samples_A_initial = posterior_A_initial.rvs(n_samples)
samples_B_initial = posterior_B_initial.rvs(n_samples)
samples_A_updated = posterior_A_updated.rvs(n_samples)
samples_B_updated = posterior_B_updated.rvs(n_samples)

# AがBより優れている確率を計算
prob_A_better_than_B_initial = np.mean(samples_A_initial > samples_B_initial)
prob_A_better_than_B_updated = np.mean(samples_A_updated > samples_B_updated)

# プロット
plt.figure(figsize=(14, 8))

# 初期の事後分布と更新後の事後分布をプロット
plt.subplot(2, 1, 1)
plt.plot(x, prior.pdf(x), 'k--', label='Prior Distribution (Beta(1,1))')
plt.plot(x, posterior_A_initial.pdf(x), 'b-', label=f'Initial Posterior A (Beta({alpha_A_initial}, {beta_A_initial}))\nP(A > B) = {prob_A_better_than_B_initial:.2f}')
plt.plot(x, posterior_B_initial.pdf(x), 'r-', label=f'Initial Posterior B (Beta({alpha_B_initial}, {beta_B_initial}))')
plt.title('Prior and Initial Posterior Distributions of Conversion Rate')
plt.xlabel('Conversion Rate')
plt.ylabel('Density')
plt.legend()
plt.grid(True)

plt.subplot(2, 1, 2)
plt.plot(x, posterior_A_updated.pdf(x), 'b-', label=f'Updated Posterior A (Beta({alpha_A_updated}, {beta_A_updated}))\nP(A > B) = {prob_A_better_than_B_updated:.2f}')
plt.plot(x, posterior_B_updated.pdf(x), 'r-', label=f'Updated Posterior B (Beta({alpha_B_updated}, {beta_B_updated}))')
plt.title('Updated Posterior Distributions of Conversion Rate')
plt.xlabel('Conversion Rate')
plt.ylabel('Density')
plt.legend()
plt.grid(True)

# グラフの表示
plt.tight_layout()
plt.show()

結論

ベイジアンABテストではテスト期間を延長しても問題なく、むしろそれが方法論の利点の一つである

テスト期間の延長によって新しいデータを追加し、事後分布を更新しながら、より信頼性の高い結論を導くことができる

この柔軟性はベイジアンアプローチが特に動的な環境での意思決定に適している

いいなと思ったら応援しよう!