3. 特征工程基础:特征分类、特征衍生、特征存储格式

特征工程是风控模型从原始数据到有效预测能力的核心桥梁。在坏账率回测哨兵系统中,特征的质量直接决定哨兵能否在早期准确识别资产质量恶化信号。本章从特征分类、特征衍生、存储格式三个维度,建立特征工程的基础知识体系。

3.1 特征分类:从数据源到业务语义

风控场景中的特征可按数据来源、时间窗口、业务含义三个维度进行分类。不同分类方式对应不同的处理策略和存储要求。

分类维度 特征类型 典型示例 处理要点
数据来源 用户画像特征 年龄、性别、职业、学历 缺失值填充、异常值截断
行为序列特征 近30天登录次数、浏览时长 时间窗口聚合、趋势计算
外部征信特征 征信查询次数、多头借贷数 数据对齐、时效性校验
时间窗口 静态特征 注册时间、首笔借款金额 一次性计算,无需更新
动态特征 近7天逾期率、近3月平均额度 滑动窗口计算,需定期刷新
业务含义 还款能力特征 收入负债比、可用额度 衍生逻辑复杂,需业务规则
还款意愿特征 历史逾期天数、催收响应率 需结合行为序列建模
实践建议:在哨兵系统中,动态特征和外部征信特征对坏账率波动的敏感度最高,建议优先构建这两类特征的自动化回测管道。

3.2 特征衍生:从原始数据到高价值信号

特征衍生是将原始字段转化为更具预测能力的特征变量的过程。在风控回测场景中,常用的衍生方法包括统计聚合、时间窗口计算、比率构造、交叉组合等。

3.2.1 常用衍生方法

  • 统计聚合:对数值型字段计算均值、最大值、最小值、标准差、分位数等。
  • 时间窗口计算:按固定时间窗口(7天、30天、90天)滑动计算统计量。
  • 比率构造:两个相关字段的比值,如逾期金额 / 总应还金额。
  • 交叉组合:类别型字段的笛卡尔积,如职业 × 城市等级。
  • 排序编码:对类别型字段按目标变量均值排序后编码。
坏账率回测场景示例:原始字段包含应还日期和实际还款日期,可衍生出逾期天数、是否逾期、逾期次数(近6个月)、最大逾期天数等特征,这些特征对坏账率预测的贡献度通常排名前10。

3.2.2 特征衍生代码示例

import pandas as pd
import numpy as np

# 原始数据示例
df = pd.DataFrame({
    'user_id': [1001, 1002, 1003],
    'due_date': pd.to_datetime(['2024-01-15', '2024-02-10', '2024-03-05']),
    'repay_date': pd.to_datetime(['2024-01-14', '2024-02-15', '2024-03-10']),
    'loan_amount': [5000, 10000, 8000],
    'repay_amount': [5000, 10000, 7500]
})

# 特征衍生:逾期天数
df['overdue_days'] = (df['repay_date'] - df['due_date']).dt.days
df['overdue_days'] = df['overdue_days'].clip(lower=0)

# 特征衍生:还款率
df['repay_ratio'] = df['repay_amount'] / df['loan_amount']

# 特征衍生:是否逾期(二值化)
df['is_overdue'] = (df['overdue_days'] > 0).astype(int)

print(df[['user_id', 'overdue_days', 'repay_ratio', 'is_overdue']])

3.3 特征存储格式:Parquet vs Feather

在特征服务与回测系统中,特征数据的存储格式直接影响读写性能、存储成本和计算效率。Parquet 和 Feather 是当前最主流的两种列式存储格式,适用于不同场景。

3.3.1 格式对比

对比维度 Parquet Feather
压缩率 高(支持 Snappy、Gzip、Zstd) 低(仅支持 LZ4、Zstd)
读写速度 读取快,写入较慢 读写均快(专为 Pandas 优化)
跨语言支持 广泛(Spark、Hive、Presto 等) 有限(主要 Python/R)
Schema 演进 支持(列添加/删除) 不支持
适用场景 长期存储、数据湖、分布式计算 中间结果、快速迭代、单机分析
文件大小 小(压缩后通常为 CSV 的 20%-30%) 中等(压缩后为 CSV 的 50%-70%)
选型建议:在哨兵回测系统中,建议使用 Parquet 存储历史回测特征数据,利用其高压缩率和 Schema 演进能力降低存储成本;使用 Feather 存储中间计算特征,利用其高速读写特性加速迭代开发。

3.3.2 读写代码示例

import pandas as pd
import pyarrow.parquet as pq
import pyarrow.feather as ft

# 创建示例特征数据
feature_df = pd.DataFrame({
    'user_id': range(1, 100001),
    'overdue_days_30d': np.random.randint(0, 30, 100000),
    'avg_loan_amount_90d': np.random.uniform(1000, 50000, 100000),
    'repay_ratio_6m': np.random.uniform(0.5, 1.0, 100000),
    'is_overdue_flag': np.random.choice([0, 1], 100000, p=[0.9, 0.1])
})

# 写入 Parquet(推荐用于长期存储)
feature_df.to_parquet('features_historical.parquet', compression='snappy')

# 写入 Feather(推荐用于中间结果)
ft.write_feather(feature_df, 'features_intermediate.feather')

# 读取验证
df_parquet = pd.read_parquet('features_historical.parquet')
df_feather = ft.read_feather('features_intermediate.feather')

print(f"Parquet 行数: {len(df_parquet)}, Feather 行数: {len(df_feather)}")

3.4 特征工程在哨兵系统中的位置

下图展示了特征工程在坏账率回测哨兵系统中的核心位置,以及特征分类、衍生、存储三个环节的协作关系。

特征工程在哨兵系统中的位置 特征工程在坏账率回测哨兵系统中的位置 原始数据源 特征分类 特征衍生 特征存储 哨兵回测引擎 说明: 1. 原始数据源经过特征分类(静态/动态、画像/行为/征信)后进入特征衍生环节。 2. 特征衍生通过统计聚合、时间窗口、比率构造等方法生成高价值特征。 3. 衍生后的特征以 Parquet/Feather 格式存储,供哨兵回测引擎调用。 4. 回测结果反馈至特征工程,形成特征迭代优化的闭环。

3.5 特征存储选型决策流程

在实际项目中,特征存储格式的选择需要综合考虑数据量、访问模式、计算环境等因素。以下决策流程可帮助快速确定合适的存储方案。

特征存储选型决策流程 特征存储选型决策流程 数据量 > 100GB? Parquet + Snappy 需要跨语言共享? Parquet Feather 是 否 是 否
实战经验:在哨兵回测系统中,建议将特征数据按时间分区存储(如year=2024/month=01/),配合 Parquet 的谓词下推功能,可大幅提升回测时的数据读取效率。Feather 更适合在单次回测任务中作为中间缓存使用,避免重复计算。