机器学习 基础教程

机器学习 集成学习

机器学习 笔记

python 实现的假设检验(融合 t 检验和 z 检验)在机器学习中应用

机器学习 笔记 机器学习 笔记


在机器学习中,有些统计特征可以通过假设检验进行满足检测的最小概率,并将其作为一个重要的特征,如 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))