在当今世界,很难想象没有A / B测试的产品开发。 要成功启动产品或新功能,您需要正确设计A / B,计算并解释其结果。 有时我们需要对两个以上的组进行测试。 在本文中,我们将考虑这种情况-多次测试:
- 我们将讨论何时以及为什么进行多次测试;
- 考虑计算测试结果的主要方法以及这些方法所基于的数学原理;
- 我们举例说明该方法的软件实现; 您可以在项目中使用这些示例。
因此,让我们开始吧。

多次实验:何时以及为什么
显然,实验的任何技术复杂性都应根据实际需要来证明。 这也适用于多个测试。 如果将受众划分为两个以上的子组,则在实验期间发生第一类错误的可能性将呈指数增长:
在哪里
-子组数,
-给定的统计显着性水平。
因此,当在普通配对测试中仅添加一个附加子组时(
)以给定的标准水平
我们得到第一种错误的可能性
大大超过了我们的目标
。
如果降低实验结果的准确性,为什么还要进行多次实验? 可能有几个原因:
- 需要测试一些更改及其对产品指标的累积影响。 一个示例在服务页面上向用户显示两个相对位置彼此不同的新元素。
- 更改只能在一个时间段内进行测试,因为它们既相互依赖又对每周的季节性敏感。 一个示例是禁用广告渠道以计算渠道间的同类化效果。
- 客户希望尽快,更便宜地获得答案,应该选择哪个选项,同时节省实验的开发和实施。
如果我们面临这些问题之一,并且我们必须计算该测试的统计显着性-我们需要考虑对多次测试进行更正的必要性。 关于它是什么以及如何正确执行,将在下面进行讨论。
多次实验:计算功能
基本概念
考虑我们处理的一般情况
假设
,
关于中位数或平均值的成对相等
亚组。 在这种情况下,正确和错误的结果都是可能的。
对于每个
假设。 将结果显示为混淆矩阵实验:
因此错误地拒绝了
来自
拒绝了基本假设。
基于这些参数,我们引入了两个重要的错误概念,这些概念在多次测试中得到控制:
和
。
组错误概率
(家庭明智的错误率)是至少获得一种第一类错误的概率,由以下公式确定:
(错误发现率)是第一类错误与主要假设的偏差总数之比的数学期望:
考虑使用标准产品案例的示例来控制这些错误的方法。
案例描述
举一个简单的例子,考虑一个实验,其中向三个孤立的,不相交的用户组显示了三个页面选项,并提供了单击广告的呼叫按钮的条件。 作为简化计算的基本指标,我们采用每个组中的总呼叫数。
让我们看看所研究的指标如何变化:
图 1.按下通话按钮的动态图
我们将使用标准方法
为了使目标指标在样本中的分布恢复正常,并查看样本中平均值的直方图和范围图:
图 2.组中平均值分布的直方图
图 3.分组平均值的范围
从图表来看,C组以呼叫按钮上的点击次数获胜。 但是,有必要验证结果的统计意义。 为此,我们将估算的指标转化为正态分布的形式,并使用通常的Student t标准对实验中的组进行成对比较,然后采用-控制方法
和
考虑到多个比较的更正。
FWER控制
有很多方法可以控制此错误,但最常见的是两种:
1)一步调整同时调整
对于使用Bonferroni方法的所有检验假设;
2)顺序,迭代调整
c根据希尔方法的结果在每一步做出决策。
1. Bonferroni修正案
这一一步的过程减少了假阳性实验结果的可能性。 该方法的本质是在以下情况下接受替代假设:
在哪里
-检验假设的数量。
使用标准库可以很简单地实现该方法
:
from bootstrapped import bootstrap as bs from bootstrapped import compare_functions as bs_cmp from bootstrapped import stats_functions as bs_st bs_ab_estims = bs.bootstrap_ab(np.array(group_A), np.array(group_B), bs_st.mean bs_cmp.difference, num_iterations=5000, alpha=0.05/3, iteration_batch_size=100, scale_test_by=1, num_threads=4) bs_bc_estims = bs.bootstrap_ab(np.array(group_B), np.array(group_C), bs_st.mean bs_cmp.difference, num_iterations=5000, alpha=0.05/3, iteration_batch_size=100, scale_test_by=1, num_threads=4) bs_ac_estims = bs.bootstrap_ab(np.array(group_A), np.array(group_C), bs_st.mean bs_cmp.difference, num_iterations=5000, alpha=0.05/3, iteration_batch_size=100, scale_test_by=1, num_threads=4)
获得统计评估的结果后,我们可以得出结论,各组是否不同。
该方法的主要缺点是:子组越多,准则的功效越低,这增加了接受错误假设的可能性。 例如,对于十个测试和
需要得到
可以说差异很大。 要消除这些缺点,可以选择Hill方法。
2.希尔法
这是一个向下的顺序更改过程。
。 在方法算法的第一步,实数
升序排列:
然后原来的
级:
之后检查条件
并得出主要假设是否正确
。
算法断点-接受第一个主要假设的时刻i
,以及所有后续
。
您可以使用以下步骤实现此方法
从图书馆
带参数
:
from bootstrapped import bootstrap as bs from bootstrapped import stats_functions as bs_st from scipy.stats import ttest_ind from statsmodels.sandbox.stats.multicomp import multipletests bs_a = bs.bootstrap(np.array(group_A), stat_func=bs_st.mean, num_iterations=10000, iteration_batch_size=300, return_distribution=True) bs_b = bs.bootstrap(np.array(group_B), stat_func=bs_st.mean, num_iterations=10000, iteration_batch_size=300, return_distribution=True) bs_c = bs.bootstrap(np.array(group_C), stat_func=bs_st.mean, num_iterations=10000, iteration_batch_size=300, return_distribution=True) stat_ab, p_ab = stats.ttest_ind(pd.DataFrame(bs_a), pd.DataFrame(bs_b)) stat_bc, p_bc = stats.ttest_ind(pd.DataFrame(bs_b), pd.DataFrame(bs_c)) stat_ac, p_ac = stats.ttest_ind(pd.DataFrame(bs_a), pd.DataFrame(bs_c)) print(sorted([p_ab, p_bc, p_ac])) print("FWER: " + str(multipletests(sorted([p_ab, p_bc, p_ac]), alpha=0.05, method='holm', is_sorted = True)))
FDR控制
控制权
表示满足条件
。 同时
,即控制中出现一阶错误的概率
下降。
本杰米尼-霍奇伯格法
此自下而上的过程涉及顺序更改。
预排序升序:
然后来源
-level由公式调整:
然后,像霍尔姆法一样,检查条件
并得出主要假设是否正确
和所有后续
。
可以使用以下过程来实现Benjamini-Hochberg方法以及Holm方法
:
print("FDR: " + str(multipletests([p_ab, p_bc, p_ac], alpha=0.05, method='fdr_bh', is_sorted = False)))
结论
在本文中,我们讨论了评估多个测试结果的主要方法,并提供了实现这些方法的程序代码示例。 我们希望您度过了有益而有趣的时光,并且能够将所描述的过程付诸实践。 如果您有任何问题,我们将很乐意为您解答。
感谢您的关注!