3. 特征工程基础:特征分类、构造与选择

大家好,我是你们的老朋友。今天咱们聊聊特征工程——说白了,这是整个欺诈识别模型里最吃功夫的一环。模型再牛,喂进去的是垃圾,出来的还是垃圾。我见过太多团队把精力全砸在调参上,结果特征没做好,模型死活提不了几个点。嗯,咱们今天就把这块硬骨头啃下来。

3.1 特征分类:先搞清楚你手里有什么牌

做特征之前,得先分清楚数据类型。我个人习惯把特征分成三大类:数值型、类别型、时序型。每种类型处理方式完全不同,混着用会出大问题。

3.1.1 数值型特征

就是那些可以直接做加减乘除的字段。比如交易金额、用户年龄、账户余额。这类特征最直接,但坑也最多。

⚠️ 我曾经踩过的坑: 金额字段直接扔进模型,结果因为量纲差异太大(有的几块钱,有的几百万),模型完全被大数值特征带偏了。后来我养成了习惯——数值型特征进来,先做标准化或归一化。

常用的处理方式:

  • 标准化(Z-score):适合数据近似正态分布的场景
  • 归一化(Min-Max):把数据压缩到[0,1]区间,适合有边界的数据
  • 对数变换:处理长尾分布,比如交易金额经常是幂律分布
# 我常用的数值特征处理代码
import numpy as np
from sklearn.preprocessing import StandardScaler, MinMaxScaler

# 对数变换处理长尾分布
amount_log = np.log1p(df['transaction_amount'])

# 标准化
scaler = StandardScaler()
amount_scaled = scaler.fit_transform(df[['amount']])

3.1.2 类别型特征

性别、设备类型、城市、IP段……这些不能直接做运算。你想想看,把“北京”和“上海”做加法,有意义吗?没有。

处理方式:

  • 独热编码:最基础,但类别太多时维度爆炸
  • 标签编码:给每个类别一个数字,但会引入大小关系(慎用)
  • 目标编码:用目标变量的均值替代类别,我在欺诈场景里经常用
💡 我的经验: 欺诈场景里,类别型特征往往藏着重要信息。比如某个IP段频繁出现欺诈,用目标编码就能把这个信号抓出来。

3.1.3 时序型特征

交易时间、登录时间、注册时间……这类特征最容易被忽视。但说实话,欺诈行为在时间上往往有规律可循。

我一般会提取:

  • 时间窗口特征:过去1小时、24小时内的交易次数
  • 周期性特征:是工作日还是周末?凌晨还是白天?
  • 间隔特征:上次交易到现在过了多久?

3.2 特征构造方法:从原始数据里挖金子

原始特征往往不够用。你得自己动手造特征。我总结了三个最实用的方法:聚合统计、比率特征、差分特征。

3.2.1 聚合统计特征

说白了,就是按某个维度分组,然后算统计量。比如按用户ID分组,算他过去7天的交易次数、平均金额、最大金额。

# 聚合统计特征示例
import pandas as pd

# 按用户分组,计算过去7天的统计量
user_stats = df.groupby('user_id')['amount'].agg([
    ('count_7d', 'count'),
    ('mean_7d', 'mean'),
    ('max_7d', 'max'),
    ('std_7d', 'std')
]).reset_index()

我在项目中遇到过,单纯靠聚合统计特征,就能把AUC提升3-5个点。为什么?因为欺诈分子往往在短时间内频繁操作,聚合特征能捕捉到这种异常行为模式。

3.2.2 比率特征

比率特征是我个人最偏爱的。它能把两个数值的关系压缩成一个有意义的指标。

常用比率:

  • 金额/次数:平均每笔交易金额
  • 失败次数/总次数:失败率
  • 登录次数/交易次数:操作效率
🔑 核心思路: 比率特征能消除量纲影响,直接反映行为模式。比如正常用户和欺诈分子的“失败率”往往差异巨大。

3.2.3 差分特征

差分特征专门处理时序数据。它衡量的是“变化量”,而不是“绝对值”。

# 差分特征示例
# 计算相邻两次交易的时间间隔
df['time_diff'] = df.groupby('user_id')['timestamp'].diff().dt.total_seconds()

# 计算金额的变化量
df['amount_diff'] = df.groupby('user_id')['amount'].diff()

你想想看,正常用户每次交易金额波动不大,但欺诈分子可能突然刷一笔大额。差分特征就能把这个信号放大。

3.3 特征选择:别让垃圾特征拖后腿

特征造了一大堆,但并不是越多越好。冗余特征会降低模型性能,还会增加过拟合风险。特征选择就是帮你做减法。

3.3.1 过滤法

最简单粗暴。算每个特征和目标变量的相关性,低于阈值的直接扔掉。

  • 皮尔逊相关系数:适合线性关系
  • 互信息:能捕捉非线性关系
  • 方差阈值:方差太小的特征,信息量有限
⚠️ 注意: 过滤法虽然快,但忽略了特征之间的交互作用。两个单独看都很弱的特征,组合起来可能很强。我一般把过滤法当作初筛工具。

3.3.2 包裹法

把特征选择看作一个搜索问题。每次选一个特征子集,训练模型看效果,反复迭代找到最优组合。

常用方法:

  • 递归特征消除(RFE):每次去掉最不重要的特征
  • 前向选择:从空集开始,逐步添加特征
  • 后向消除:从全集开始,逐步删除特征

包裹法效果好,但计算成本高。我通常只在特征数量不多(比如50个以内)时使用。

3.3.3 嵌入法

这是我最推荐的方法。特征选择和模型训练同时进行,效率高且效果好。

典型代表:

  • L1正则化(Lasso):自动把不重要特征的系数压到0
  • 树模型特征重要性:XGBoost、LightGBM自带特征重要性排序
# 使用Lasso进行特征选择
from sklearn.linear_model import Lasso

lasso = Lasso(alpha=0.01)
lasso.fit(X_train, y_train)

# 系数不为0的特征就是被选中的
selected_features = X_train.columns[lasso.coef_ != 0]
💡 我的习惯: 先用过滤法快速筛掉明显没用的特征,再用嵌入法做精细选择。如果资源允许,最后用包裹法微调。三层筛选下来,特征质量基本有保障。

3.4 知识体系总览

下面这张图是我自己画的,把特征工程的整个流程串起来了。你可以把它当作一个检查清单——每次做特征工程时,对着这张图过一遍,基本不会漏掉关键步骤。

特征工程知识体系总览 原始数据 特征分类 数值型 类别型 时序型 特征构造方法 聚合统计 比率特征 差分特征 特征选择 过滤法 包裹法 嵌入法 最终特征集 从原始数据到最终特征集,每一步都影响模型效果

好了,特征工程这块的内容就到这里。记住一句话:特征决定了模型的上限,算法只是逼近这个上限。把特征做扎实了,模型效果自然就上来了。

专注资料整理