我们做完AB实验后,最终难免需要比较AB两组用户的数据差异,进而根据结果的好坏,来决定如何取舍方案。
但是两组数据之间的差异,并不总是像我们想象的那么明显,有时候仅仅是微弱的差别。而且这种差别还存在一定的波动性,比如某段时间内A组数据可能好些,某段时间B组可能好些。
那么,我们怎么样才能确定AB两组的差异是真实存在的呢?
这就引入了统计检验的概念。
统计检验的通俗解释
统计检验。简单来说,就是要我们观察到的两组差异,比偶然差异大得多,我们就认为两组之间的差异是真实存在的。
更准确地说,通过一系列计算后,如果我们发现两组之间的差异,比两组之间因为误差导致的差异更大,且突破了一定的阈值时。我们就认为实验效果是显著的。
那么接下来,问题变成了我们该如何评估偶然误差,以及如何衡量阈值了。
偶然误差
我们以常用的独立样本T检验为例,进行说明。
偶然误差一般用组内的变异来说明。所谓变异,即组内各个值和组内整体均值之间的差距。
统计学上,这种差距一般可以用标准差来表示(可以理解为每个样本值和均值的差异平方,除以样本量,再开方)。
![d06ee2ff3f3dfb70012fec1d3d777eb0.png](https://i-blog.csdnimg.cn/blog_migrate/0fbaf2a76f81dc5d5fbae372586cf169.png)
标准差越大,说明组内数据波动越大,越不稳定。
对独立样本T检验(比较两组不同用户的数据差异)而言,标准差具体的计算方式为
其中
知道了误差,下一步就是衡量误差是否超过阈值了。
衡量阈值
对于阈值部分来说,我们一般考虑差异的偶发程度。
大部分样本数据都会遵循正态分布(两组数据的差也一样),在这种情况下,绝大部分数据值都会跟均值相差不远。离群值越极端,出现的概率也就越低。
如果我们把各个极端值出现的概率描绘出来,会近似为下面这张图。
![3807b42fa9fbbb4e866312de10900af6.png](https://i-blog.csdnimg.cn/blog_migrate/44db5d54ef91026e11302f276fe63b60.jpeg)
图中纵坐标为密度,横坐标为可能的结果值,曲线下的面积代表真实值落在某个值段的概率。
显然,我们可以看到大部分数据都集中在中间部分,两端的极端值都相对较少。
图中的阴影部分,就是极端值出现的概率,因为他们非常靠近两端,是真正的小概率事件。阴影对应的极端阈值u,就是我们定义的阈值判断标准。
假如我们算出的两组差异值,超过了+u或者小于-u的值,就都算是极端值(换句话说,即两组数据的差异,不像是偶然的误差导致)。
图中阴影面积是可以由我们自己设定的,它的值通常用α来代表。比如本例示范为双尾检测(同时判断大于+u或者小于-u两种情况),因此其值为α/2。
α的取值一般为0.05、0.01,可以近似理解为结果的可信度。α越小,意味着AB之间的差异越罕见,越不可能是偶发误差。当然,α越小,对应的实验要求也就越高。
理解了上述内容,我们再来看看实践里用到的独立样本T检验。
当样本量比较小的时候,分布会类似于正态分布,但是会更加扁平一些。(背后的原因,是因为Z检验对应的正态分布是已知了整体方差,用整体来直接计算Z值。而T检验是使用部分样本来估计总体,样本量小时,正态分度不会那么明显)。
T检验遵循的就是这样一种分布。
![788be37dec806c231945b737aa858107.png](https://i-blog.csdnimg.cn/blog_migrate/52a95fb3c57f61160cccc3ce15d151a7.png)
在不同的α(显著性水平)和样本量下,T检验会有不同的分布。
而在某个具体的分布下,我们可以知道某个概率阈值对应的T分数阈值(也就是前文所说的+-u值)。这个+-u值通常查表或者计算可知。
接下来只需要比较实验计算出的T分数和这个T分数阈值之间的差别,即可判断实验效应是否显著(如果差异很极端,我们就认为它不是偶然因素)。
下面,我们看看一个T检验的基本过程。
T检验过程
说了那么多,T分数怎么计算呢?有个基本公式:
其中的S值,可以参考前面的公式。
然后是阈值。
阈值一般是通过查表的方式获取。可以在网上搜索下“T检验临界值表”。当然,一般的软件统计包或者工具里面都会自带这个值。
![28fd651d814e8d01588d2ee4ed318ad0.png](https://i-blog.csdnimg.cn/blog_migrate/d624981655cc7e93a2141bc0bb0af4ea.jpeg)
根据样本量和α值,我们可以找到临界T值。
接下来,我们只需要比较T值和阈值之间的差,就能判断实验是否真的有效了。
T检验的注意事项
当然,使用T检验也有一些注意事项。比如:
- 1.来自正态分布总体。
- 2.两样本总体方差相等,即具有方差齐性。
当然,一般来说,随机采样的大样本会默认符合这两个条件(参考文章)。
在日常做分析的过程中,我们也会进行F检验,判断两组数据之间的方差是否有差异。如果有差异,我们会选择Welch法近似t检验进行替代。有兴趣的读者可以自行搜索了解。
此外,T检验主要适用于两组数据之间的比较,至于多组数据的对比,T检验并不适用。
这个时候方差分析会是更好的选择。
- 方差分析可以同时分析多组之间的差异,因而减少犯统计错误的可能性
- 方差分析还可以分析多个组之间的交互作用
感兴趣的读者可以自行查阅研究。
T检验工具
常见的统计工具如SPSS、Excel、python都可以进行T检验。
下面以python代码举例,为大家提供分析参考。
import pandas as pd
from scipy import stats
import numpy as np
import math
from scipy.stats import norm
path = "test.csv"
data = pd.read_csv(path,header=0,index_col=None,sep=",")
def statistic_abtest(control_data,experiment_data,info):
print("开始计算 {} 的置信区间...".format(info))
levene_t, levene_p = stats.levene(experiment_data,control_data)
print("levene 方差 {}, p_value = {} :".format(levene_t,levene_p))
equal_var = True
if levene_p<0.05: # 说明方差有显著差异
equal_var = False
t_t, t_p = stats.ttest_ind(control_data,experiment_data,equal_var=equal_var)
print("t检验 {}, p_value = {} :".format(t_t,t_p))
significance_level = "没有显著变化!"
if t_p <= 0.05:
significance_level = "实验组有显著变化! (可能显著变好,有可能显著变差)"
def _mean(x):
return sum(x)/len(x)
def _standard_deviation(x):
mean = _mean(x)
standard_deviation = math.sqrt(sum([(x[i] - mean)**2 for i in range(len(x))])/len(x))
return standard_deviation
def confidence_u(x1: float, x2: float, s1: float, s2: float, n1: int, n2: int, a: float) -> tuple:
'''
双样本均值检验
:param x1: 样本均值
:param x2: 样本均值
:param s1: 样本标准差
:param s2: 样本标准差
:param n1: 样本量
:param n2: 样本量
:param a: alpha
:return: 置信区间
'''
d = norm.ppf(1 - a / 2) * pow(s1 ** 2 / n1 + s2 ** 2 / n2, 1 / 2)
floor = x1 - x2 - d
ceil = x1 - x2 + d
return (format(floor, '.4f'), format(ceil, '.4f'))
def confident_area(x,y):
mean_x = _mean(x)
mean_y = _mean(y)
sd_x = _standard_deviation(x)
sd_y = _standard_deviation(y)
confi = confidence_u(mean_x,mean_y,sd_x,sd_y,len(x),len(y),0.05)
print("levene方差 p_value = {}, t检验p_value = {}, significance_level = {}".format(levene_p,t_p,significance_level))
print("control_samples = {}, experiment_samples = {}".format(len(y), len(x)))
print("control_mean = {}, experiment_mean = {}".format(mean_y,mean_x))
print("control_standard_deviation = {}, experiment_standard_deviation = {}".format(sd_y, sd_x))
print("confidence interval = {}. 置信区间全为正区间表示实验组显著优于对照组,全为负区间表示实验组差于对照组".format(confi))
confident_area(experiment_data,control_data)
print("结束计算 {} 的置信区间...".format(info))
for _ in range(5):
print("t")
control_data = data["A"].values
experiment_data = data["B"].values
statistic_abtest(control_data,experiment_data,"info")
使用的时候,修改文件目录,以及对应的AB组数据(control_data、experiment_data)即可。
以上代码默认α值为0.05,如果有特殊需求,可以灵活修改。
T检验结果解读
T检验会产生一系列结果参数,理解了它们,才能知道结果如何。
下面是SPSS的一个独立样本T检验结果,因为它的格式比较规范,我们用它来作说明。
python的结果类似,可以在此基础上自行理解。
![2416c7eb31c8c5ab8eb2f192df9dd5de.png](https://i-blog.csdnimg.cn/blog_migrate/f1c3cca0a00536ac071b89828ab379cb.jpeg)
- 组统计部分描述了样本的大概情况,包括样本个案数、平均值、标准差、标准误等等。
- 样本检验部分说明了统计检验的结果:
- 莱文方差显著(F列后面的显著性<=0.05),则看假定方差相等的那一行。如果不显著(F列后面的显著性>0.05),则看假定不相等那一行。
- 平均值T检验部分,展示了一系列指标,包括具体的t值、自由度(样本量-1)、显著性P值、两组均值差异、标准误、上下端置信区间阈值等。
- 我们重点关心Sig双尾是否低于0.05/0.01,分别对应95%置信度和99%置信度。如果低于,我们认为两组之间的差异显著(真实存在)。换句话说,实验条件,带来了指标差异。
需要注意的是,实验越显著,并不代表实验效果越大。因为显著性只是说明差异真实存在,而不是说差异非常大。
对于提升量来说,我们一般会参考提升度指标:(实验组均值-对照组均值)/对照组均值。
因此,实验结束后,我们会提供两个信息,一个是差异是否存在(显著性),另一个是差异度如何(是正是负,具体提升度多少)。