scipy.stats.skew和kurtosis默认bias=true,小样本下系统性高估偏度峰度绝对值,且kurtosis默认返回excess kurtosis(正态为0),非原始峰度(正态为3),故不能直接作为机器学习特征使用。

直接说结论:scipy.stats 不适合直接“处理”机器学习中的高阶统计特征,它只负责计算——偏度、峰度、分位数等指标本身不是特征,而是你手动构造特征的原材料。
很多人误以为调用 stats.skew 或 stats.kurtosis 就算“做了高阶统计特征工程”,其实只是完成了最前端的数值计算。真正落地到模型里,需要你明确场景、封装逻辑、控制偏差,并警惕默认参数带来的误导。
为什么 stats.skew 和 stats.kurtosis 的默认结果不能直接当特征用?
这两个函数默认使用 bias=True,即不校正样本偏差。小样本(比如每条样本是 10 个时序点)下,skew 和 kurtosis 会系统性高估绝对值,尤其峰度在 n
- 真实业务中,如果你对每个用户滑动窗口计算 7 天销售额的偏度,窗口长度仅 7,
stats.skew(x, bias=True)给出的值大概率失真 -
fisher=True(默认)的峰度以正态分布为 0 基准,但很多业务分布本就不接近正态,这个“偏离程度”解释力很弱 - 它们都忽略 NaN 处理策略:
nan_policy='propagate'会让整条特征向量变NaN,而实际中你更可能想跳过或插补
如何把 skew/kurtosis 变成稳定可用的特征?
关键不是“怎么算”,而是“怎么定义”。例如金融风控中,你真正关心的不是“该用户近 30 笔交易金额的峰度是多少”,而是“其尾部波动是否显著高于同类人群”。这就需要:
- 先用
stats.kurtosis(data, fisher=False, bias=False)得到 Pearson 峰度(正态=3),再减去群体均值做标准化,得到相对峰度 - 对偏度做符号保留但截断:小于 -3 或大于 +3 的值设为边界值,避免异常点污染后续模型
- 组合使用:比如
abs(skew) * np.log1p(kurtosis),强化“不对称+厚尾”的联合信号,在反欺诈场景中比单独用任一指标更鲁棒 - 必须配合
axis显式指定维度:传入二维数组时,axis=1才是对每行(每个样本)独立计算;默认axis=0会错算成按列聚合
describe() 返回的 Result 对象容易被误用
stats.describe 看起来省事,但它返回的是 DescribeResult 命名元组,字段名固定且不可配置。常见陷阱:
-
skewness和kurtosis字段默认仍是bias=True,和单独调用skew()行为一致,没解决偏差问题 - 无法控制
nan_policy—— 它没有这个参数,遇到 NaN 直接报ValueError,不像单函数可设为'omit' - 返回的
minmax是 tuple,取最小值得写res.minmax[0],容易漏括号导致运行时报错 - 如果你只需要偏度和峰度,却调了
describe,等于多算了均值、方差、计数等冗余字段,纯属浪费
真正要落地,别图省事。该拆开调就拆开调,显式传参,逐个校验输出形状和 NaN 行为——高阶统计特征的价值,全系于你对每个数字来源的掌控力。稍一模糊,它们就从信号变成噪声。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











