我们在做AB测试时,需要用到很多的统计知识,如最小样本量、检验方法等,在这些方法之前有一个大的前提,构造检验的统计量要服从正态分布,然后才能进行接下来的统计量、p值、置信区间计算,加以判断是否统计显著。那么日常所做实验是否满足这个大前提,到底多大样本量能达到正态分布的这个大前提是本篇文章主要回答的问题。
目录
一、中心极限定理与正态分布
1.1 中心极限定理
中心极限定理是指给定一个任意分布的总体,每次从这些总体中随机抽取n个样本,一共抽取m次,把这m次抽样分别求出平均值,这个平均值的分布接近正态分布。
在以往我们学习的教材中,一般还有附带有,每次抽取的样本个数n需要大于等于30,就能符合中心极限定理,并以作为大小样本量的区分,大样本量会用z检验,小样本量会用t检验等。但实际情况中,业务数据大都是偏态分布,像用户的活跃次数、交易次数、交易金额等都是严重的右偏分布,随机取的样本量过少时,我们可以通过可视化或者检验发现不一定服从正态分布。
1.2 如何判定数据是否服从正态分布
1.2.1 可视化图形法
(1)直方图
首先,我们可以画数据的直方图,观察数据是否符合正态分布。
plt.hist(x)
(2)qq图、pp图
qq图是根据观测值的实际分位数与理论分布(如正态分布)的分位数的符合程度画出来的;
pp图是根据观测值的累积概率与理论分布(如正态分布)的累积概率的的符合程度画出来的。
qq图的绘制一般先要给数据添加分位数,然后绘制分位数与分位数的拟合图
df_avg_cnt['pct'] = df_avg_cnt.avg_cnt.rank(pct = True) # 添加分位数
stats.probplot(df_avg_cnt['pct'], plot = plt) # 绘制qq图
1.2.2 ks检验
ks检验用来检验总体是否服从某一理论分布,该检验是将某一变量的累积分布函数与特定的分布函数进行比较,检验其拟合程度。其原假设是该分布与指定的理论分布无显著差异;备择假设
是该分布与指定的理论分布差异显著。根据检验的p值进行判断,p值小于指定的显著性水平时,拒绝原假设,在检验是否符合正态分布的场景中,即能做出数据不服从正态分布的结论;如果p值大于指定的显著性水平,则不能拒绝原假设,可以认为数据满足正态分布。
print('ks检验', stats.kstest(rvs = avg_cnt, cdf = 'norm'
, args = (np.mean(avg_cnt), np.std(avg_cnt))))
其参数说明:
rvs:待检验的数据
cdf:指定的理论累积分布
args:当rvs或cdf为字符串时,该数据为其分布参数,上边例子中是指理论分布为特定均值和标准的正态分布
可以看到p值为0.54,大于0.05,故不能拒绝原假设,可以认为数据服从正态分布。
二、偏态数据模拟中心极限定理
2.1 数据的偏度
实际业务中有很多数据都不服从正态分布,标准正态分布的偏度为0,峰度为3(有些统计口径会直接减3,以0作为标准),如下代码从正态分布中随机抽取1000个样本,观察其直方图,偏度、峰度。
norm_arr = np.random.normal(0, 1, 1000) # 从正态分布中随机抽取1000个样本
plt.hist(norm_arr) # 画出直方图
plt.show()
print('偏度:%6.4f,峰度:%6.4f' % (stats.skew(norm_arr), stats.kurtosis(norm_arr))) # 偏度及峰度
2.2 实际业务数据的偏度系数
我们知道从正态分布的总体总随机抽取的样本量也服从正态分布,而偏态数据分布的数据中随机抽取同样数据量样本则不一定服从正态分布。以某平台数据为例,随机抽取100w用户某月某行为的计数数据,可以发现有严重的右偏分布,其偏度为63,峰度为7699。
# data['currm_cnt']为当月每用户行为计数
data['currm_cnt'].hist(bins = 50)
plt.show()
print('偏度:%6.4f,峰度:%6.4f' % (data['currm_cnt'].skew(), data['currm_cnt'].kurt())) # 偏度及峰度
筛选当月行为数在0-10之间的用户,同样是偏态分布,但偏度和峰度都有所降低。
# 筛选当月行为次数在0-10之间的数据,共365860
data_01 = data[(data['currm_cnt'] > 0) & (data['currm_cnt'] < 10)]
data_01['currm_cnt'].hist(bins = 50)
plt.show()
print('偏度:%6.4f,峰度:%6.4f' % (data_01['currm_cnt'].skew(), data_01['currm_cnt'].kurt())) # 偏度及峰度
2.3 达到正态分布的最小样本量和数据的偏态系数成正相关
接着从以面上两个偏态数据集为例,从中抽取相同数量n的样本,进行m次,来模拟中心极限定理。分别在data、data_01两个数据集中抽取1000、5000、10000、50000样本量来进行模拟,如下是代码实例和运行结果,可以看到偏度较小的数据集data_01中,样本量为1000时,抽样分布已经符合正态分布了,偏度和峰度都接近0,ks检验的p指为0.95。而偏度严重的数据集data中,样本量要达到50000,抽样分布才能接近正态分布。验证了数据偏态越严重,要达到中心极限定理中的样本量就越大。
avg_cnt = [] # 每次抽取样本均值
# 进行1000次
for i in range(1000):
t = data['currm_cnt'].sample(n = 1000) # 随机抽取1000个样本
avg_cnt.append(t.mean()) # 求这1000个样本的平均值
plt.hist(avg_cnt) # 画出直方图
plt.show()
print('偏度:%6.4f,峰度:%6.4f' % (stats.skew(df_avg_cnt['avg_cnt']), stats.kurtosis(df_avg_cnt['avg_cnt']))) # 偏度及峰度
print('ks检验', stats.kstest(avg_cnt, 'norm', (np.mean(avg_cnt), np.std(avg_cnt))))
## qq图
df_avg_cnt = pd.DataFrame(data = avg_cnt, columns = ['avg_cnt'])
df_avg_cnt['pct'] = df_avg_cnt.avg_cnt.rank(pct = True)
stats.probplot(df_avg_cnt['pct'], plot = plt)
对于使均值服从正态分布的最小样本量,根据《关键迭代》一书中经验法则是
,其中s是总体
的偏态系数。对于data数据集偏态系数为63,所需样本量为140w,data_01数据集偏态系数为2.4,需要样本量约为2045。由以上实际实践,偏态严重的数据集data需要50000左右,能达到正态分布,data_01数集在1000时就能达到正态分布,所需的样本量小于书中的理论数据。但总体结论是,要达到正态分布的最小样本量和数据的偏度相关,偏度越大,所需样本量越大。在实际操作中可以先看数据的偏态情况,所需样本量虽然不必达到
,但可以从
开始尝试,看是否已服从正态分布。