4. 统计特征工程:均值、方差、分位数、偏度、峰度在交易中的应用
大家好,我是你们的老朋友。今天我们来聊聊统计特征工程。
说白了,就是把数学课上学的那几个统计量——均值、方差、分位数、偏度、峰度——用到交易数据里。听起来简单?嗯,但坑不少。我刚开始做风控那会儿,也踩过不少雷。
4.1 均值:交易行为的“基准线”
均值,就是平均。在交易里,它代表一个用户的“正常”行为水平。比如,一个用户过去30天平均每天交易5笔,那5就是他的基准线。
怎么用?
- 单笔金额均值:如果用户平时每笔交易平均200块,突然来了一笔20000的,那就有问题了。
- 交易频次均值:平时一天3次,今天突然30次,这明显是异常。
- 设备切换均值:用户平均每10天换一次设备,今天换了3次,嗯,要警惕。
核心思路:均值是“正常”的锚点。偏离均值越远,异常概率越大。
我个人习惯,会把均值按时间窗口切分。比如近7天均值、近30天均值。为什么?因为用户的行为会漂移。一个用户可能上个月很活跃,这个月变懒了。用全局均值会误判。
小技巧:计算均值时,记得剔除极端值。否则一个异常点就能把均值拉偏,导致后续检测失效。
4.2 方差与标准差:波动性的“温度计”
均值告诉你“正常在哪”,方差告诉你“正常有多散”。
方差大,说明用户行为不稳定,忽高忽低。方差小,说明用户行为很稳定,像个机器人。
我在项目中遇到过:一个用户交易金额的方差突然从100变成10000。一看,原来是账户被盗,黑客在疯狂小额试探。方差这个指标,比均值敏感得多。
具体应用:
- 金额方差:正常用户方差小,盗刷用户方差大(因为要试各种金额)。
- 时间间隔方差:正常用户交易间隔有规律,机器人交易间隔几乎恒定(方差极小)。
- 设备ID方差:正常用户设备稳定,异常用户设备频繁变化(方差大)。
避坑指南:我曾经用标准差直接做阈值,结果误杀率极高。为什么?因为不同用户的方差天然不同。后来我改用“变异系数”(标准差/均值),效果好了很多。
4.3 分位数:抗干扰的“稳健统计”
均值和方差有个致命弱点:对极端值敏感。一个100万的交易,能把均值从200拉到1000。
分位数就不一样。它只看排序位置,不受极端值影响。
常用分位数:
- 25%分位数(Q1):代表“小额交易”的典型值
- 50%分位数(中位数):代表“一般交易”的典型值
- 75%分位数(Q3):代表“大额交易”的典型值
- 90%/95%/99%分位数:代表“极端交易”的边界
怎么用?
我习惯用分位数做“分层检测”。比如:
- 交易金额 > Q3 + 1.5*IQR(四分位距),标记为“偏高”
- 交易金额 > Q99,直接标记为“高危”
核心逻辑:分位数天然适合做“异常阈值”。因为它不假设数据分布,什么数据都能用。
你想想看,如果用户平时交易金额的90%分位数是500块,今天突然来了一笔5000的。这比用均值判断靠谱多了。
4.4 偏度:数据分布的“不对称性”
偏度衡量数据分布是否对称。
- 偏度=0:对称分布(正态分布)
- 偏度>0:右偏(长尾在右边,有少量极大值)
- 偏度<0:左偏(长尾在左边,有少量极小值)
在交易中的应用:
正常用户的交易金额分布,通常是右偏的。为什么?因为大部分交易是小额的,偶尔有大额。偏度为正,且稳定。
异常用户的偏度会突变。比如:
- 盗刷用户:偏度突然变大(出现大量小额试探)
- 洗钱用户:偏度突然变小(交易金额变得均匀)
个人经验:偏度这个指标,单独用效果一般。我习惯把它和峰度组合起来用,形成一个“分布形状特征对”。
4.5 峰度:数据分布的“尖峰程度”
峰度衡量数据分布的“尖峰”程度。说白了,就是数据是集中在均值附近,还是分散在两边。
- 峰度=3:正态分布
- 峰度>3:尖峰分布(数据集中在均值附近,有厚尾)
- 峰度<3:平峰分布(数据分散,尾部薄)
在交易中的应用:
正常用户的交易金额峰度通常较高。为什么?因为大部分交易都集中在某个金额附近(比如100-200块)。
异常用户的峰度会降低。比如:
- 机器人交易:金额分布非常均匀,峰度接近0
- 盗刷交易:金额分布散乱,峰度降低
避坑指南:我曾经直接用峰度做特征,结果发现不同用户的峰度天然差异很大。后来我改用“相对峰度”(当前窗口峰度 / 历史窗口峰度),效果好了很多。
4.6 组合使用:统计特征工程的核心
单个统计量,效果有限。组合起来,威力翻倍。
我常用的组合方式:
| 组合 | 检测目标 | 典型场景 |
|---|---|---|
| 均值 + 方差 | 行为突变 | 账户被盗、设备更换 |
| 中位数 + IQR | 极端值检测 | 大额交易、异常金额 |
| 偏度 + 峰度 | 分布形状异常 | 机器人交易、洗钱行为 |
| 分位数 + 均值 | 分层异常检测 | 多维度风险评估 |
核心思路:不要只用一个统计量。用多个统计量从不同角度描述数据,异常检测的准确率会大幅提升。
4.7 实战代码示例
说了这么多,来点实际的。下面是我常用的统计特征计算代码:
import pandas as pd
import numpy as np
def compute_stat_features(df, group_col='user_id', value_col='amount', window=30):
"""
计算统计特征
df: 交易数据
group_col: 分组字段(用户ID)
value_col: 数值字段(交易金额)
window: 时间窗口(天)
"""
features = []
for user, group in df.groupby(group_col):
# 取最近window天的数据
recent = group.tail(window)
vals = recent[value_col].values
if len(vals) < 5: # 数据太少,跳过
continue
feat = {
'user_id': user,
'mean': np.mean(vals),
'std': np.std(vals),
'median': np.median(vals),
'q25': np.percentile(vals, 25),
'q75': np.percentile(vals, 75),
'iqr': np.percentile(vals, 75) - np.percentile(vals, 25),
'skew': pd.Series(vals).skew(),
'kurt': pd.Series(vals).kurtosis(),
'cv': np.std(vals) / (np.mean(vals) + 1e-8), # 变异系数
'q99': np.percentile(vals, 99)
}
features.append(feat)
return pd.DataFrame(features)
# 使用示例
# df = pd.read_csv('transactions.csv')
# feat_df = compute_stat_features(df)
# print(feat_df.head())
小提示:代码里我加了变异系数(CV)和99%分位数。这两个在实际项目中非常实用。变异系数解决了不同用户方差不可比的问题,99%分位数则直接定位极端值。
4.8 知识体系总览
最后,我用一张图来总结本章的核心逻辑:
这张图展示了从原始交易数据到异常检测特征的完整流程。每个统计量都有其独特的应用场景,组合使用才能发挥最大威力。