在机器学习中,有些统计特征可以通过假设检验进行满足检测的最小概率,并将其作为一个重要的特征,如 ctr 值。下面给出了,笔者在实际应用中,封装的融合 t 检验和 z 检验的 python 假设检验方法。
自定义方法
该自定义封装实现的函数,需要借助 numpy 和 scipy 库,具体如下:
from numpy import array, linspace, where
from scipy import stats
def hypothesis_test(p_sample: float, n: int, start: float = 0.01,
stop: float = 1.0, step: float = 0.01,
alpha=0.01) -> array:
"""
对总体比率做 Z 检验(Z-test)或 t 检验(T-test),由于只关注 p_sample 下限,所以该检验为左侧检验
原假设(null hypothesis) H0 -> p_sample >= p0
备择假设(alternative hypothesis) H1 -> p_sample < p0
-------------------------------------------------------------------
y = [0, 1, 0, 0, 1, 0...]
p = sum(y) / len(y)
利用 y 的平方仍然等于 y,p 就是 y 的均值这两个等式,不难证出
方差 = p * (1 - p)
Arguments:
p_sample {float} -- 样本比率
n {int} -- 样本数量
Keyword Arguments:
start {float} -- 总体比率的最小值 (default: {0.01})
stop {float} -- 总体比率的最大值 (default: {1.0})
step {float} -- 总体比率的步长 (default: {0.01})
alpha {float} -- 显著水平 (default: {0.01})
Returns:
array -- 原假设不成立的概率
"""
# 生成待检验的总体比率
num = round((stop - start) / step) + 1
p0 = linspace(start, stop, num)
# 计算总体的标准差
std = (p0 * (1 - p0)) ** 0.5
# 计算 Z 值或 T 值
Z = T = (p_sample - p0) / (std / n ** 0.5)
# 小样本采用 T 检验,计算原假设不成立的概率
if n < 30 or n * p_sample < 5 or n * (1 - p_sample) < 5:
# 计算 T 分布的累计概率密度,自由度取 n - 1
probs = stats.t.cdf(-T, df=n - 1)
# 大样本采用 Z 检验,计算原假设不成立的概率
else:
# 计算正态分布的累计概率密度
probs = stats.norm.cdf(-Z)
# 返回满足 alpha 的最小总体比率
idxs = where(probs >= alpha)[0]
if len(idxs) == 0:
# 如果所有的检测都是小概率事件,返回检测的最大概率
ret = p0[-1]
else:
# 返回检测的最小概率
idx = idxs.min()
ret = p0[idx]
return float(ret)
实际应用
如果某个 item 基于埋点统计得到 ctr 是 0.13,曝光数 impression 是 100 时,计算新特征 ctr_min_est 如下计算:
if __name__ == "__main__":
# 对 ctr 进行假设检验,增加置信度(精度:千分位)
ctr = 0.13
impression = 100
print(hypothesis_test(float(ctr if ctr else 0.001), int(impression if impression else 1), step=0.001))