1. 推荐系统特征处理概述
在推荐系统这个领域摸爬滚打多年,我深刻体会到特征工程就是推荐系统的"地基"。就像盖房子一样,地基打不好,再漂亮的模型架构都是空中楼阁。今天我们就来聊聊推荐系统中三类核心特征的处理方法,这些都是我在实际项目中反复验证过的实战经验。
推荐系统的特征主要分为三大类:类别特征(比如用户性别、商品品类)、数值特征(比如用户年龄、商品价格)、序列特征(比如用户最近点击的商品序列)。不同类型的特征就像不同材质的建筑材料,需要采用不同的加工方式才能发挥最大效用。
2. 类别特征处理方法
2.1 独热编码(One-Hot Encoding)
独热编码是最基础的类别特征处理方法。假设我们有一个"城市"特征,包含北京、上海、广州三个取值,经过独热编码后会变成三个二元特征:
北京 -> [1,0,0] 上海 -> [0,1,0] 广州 -> [0,0,1]在实际项目中,我常用sklearn的OneHotEncoder来实现:
from sklearn.preprocessing import OneHotEncoder encoder = OneHotEncoder() encoded_features = encoder.fit_transform(df[['city']])注意:当类别取值很多时(比如商品ID),独热编码会导致特征维度爆炸。这时需要考虑其他方法。
2.2 哈希编码(Hash Encoding)
对于高基数类别特征,我通常会采用哈希编码。它将类别值映射到固定大小的空间,比如将商品ID哈希到256维:
from sklearn.feature_extraction import FeatureHasher hasher = FeatureHasher(n_features=256, input_type='string') hashed_features = hasher.transform(df['item_id'].astype(str))哈希编码的优点是内存占用固定,但可能存在哈希冲突。我的经验是:当类别数超过1万时,哈希编码是更实用的选择。
2.3 嵌入编码(Embedding)
在深度学习推荐系统中,我更喜欢使用嵌入层来处理类别特征。嵌入层可以将类别特征映射到低维稠密向量:
import tensorflow as tf user_embedding = tf.keras.layers.Embedding( input_dim=num_users, output_dim=32, name='user_embedding' )嵌入向量的维度通常选择32/64/128,需要通过实验确定。我在实践中发现,对于用户ID这类特征,32维通常就足够了。
3. 数值特征处理方法
3.1 标准化(Standardization)
数值特征最常见的处理方法是标准化,也就是将特征转换为均值为0,标准差为1的分布:
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() scaled_age = scaler.fit_transform(df[['age']])标准化特别适合那些取值范围差异大的特征,比如用户年龄和收入。在我的项目中,标准化后的数值特征通常能让模型收敛更快。
3.2 分桶处理(Binning)
有时候数值特征的绝对值不如其所在区间重要。比如用户年龄,18-25岁和55岁以上可能有显著不同的行为模式。这时我会进行分桶处理:
bins = [0, 18, 25, 35, 45, 55, 100] df['age_bucket'] = pd.cut(df['age'], bins=bins)分桶后的特征可以当作类别特征处理。我的经验是:对于有明显业务含义的数值特征,分桶往往比原始数值效果更好。
3.3 对数变换(Log Transform)
对于长尾分布的数值特征(比如用户观看视频的时长),我会先进行对数变换:
df['watch_time_log'] = np.log1p(df['watch_time'])这个简单的变换能让特征分布更接近正态分布,提高模型性能。我在视频推荐项目中,这个技巧让CTR提升了约3%。
4. 序列特征处理方法
4.1 滑动窗口统计
对于用户行为序列,我常用滑动窗口计算统计量。比如计算用户最近10次点击的平均价格:
df['avg_price_last_10'] = df.groupby('user_id')['price'].rolling(10).mean().values这类特征能捕捉用户的短期兴趣。我的经验是:窗口大小通常选择7/14/30,对应一周、两周和一个月的行为。
4.2 序列嵌入
在深度学习模型中,我会用RNN或Transformer处理原始行为序列:
# 使用Transformer处理点击序列 seq_input = tf.keras.layers.Input(shape=(None,)) seq_embed = tf.keras.layers.Embedding(vocab_size, 64)(seq_input) seq_trans = tf.keras.layers.TransformerEncoder(num_heads=4, key_dim=64)(seq_embed)序列建模能捕捉用户兴趣的演变过程。我在电商推荐中,加入序列特征后转化率提升了8%。
4.3 注意力池化
对于用户历史行为序列,不同行为的重要性不同。我会使用注意力机制来自动学习权重:
attention = tf.keras.layers.Attention()([query, behavior_seq]) weighted_seq = tf.reduce_sum(attention * behavior_seq, axis=1)这种方法比简单平均更有效,能突出用户的核心兴趣点。实际项目中,注意力池化比平均池化效果提升约5%。
5. 特征组合技巧
5.1 交叉特征
单一特征往往不够,我会组合多个特征生成交叉特征。比如用户性别和商品类别的组合:
df['gender_x_category'] = df['gender'].astype(str) + '_' + df['category'].astype(str)这类特征能捕捉不同群体对不同商品的偏好差异。我的经验是:对于重要的一级类别,手动构造交叉特征很有价值。
5.2 多项式特征
对于数值特征,我会尝试生成多项式特征:
from sklearn.preprocessing import PolynomialFeatures poly = PolynomialFeatures(degree=2, interaction_only=True) interaction_features = poly.fit_transform(df[['age', 'income']])这能帮助模型学习特征间的交互作用。但要注意,高阶多项式特征可能导致过拟合。
5.3 基于业务逻辑的特征
最有价值的特征往往来自业务理解。比如在视频推荐中,我会计算:
df['watch_completion_rate'] = df['watch_duration'] / df['video_duration']这类特征直接反映了用户兴趣强度。我的建议是:花时间理解业务,设计有明确意义的特征。
6. 特征处理实战经验
6.1 特征重要性分析
在特征工程后,我会用模型分析特征重要性:
from sklearn.ensemble import RandomForestClassifier model = RandomForestClassifier() model.fit(X_train, y_train) importance = model.feature_importances_这能帮助识别哪些特征真正有用。我经常发现,30%的特征贡献了90%的效果。
6.2 线上线下一致性检查
特征处理的一个常见陷阱是线上线下不一致。我会在预处理代码中加入严格检查:
assert set(train_data['city'].unique()) == set(test_data['city'].unique())这个简单的断言帮我避免过多次线上事故。教训是:特征处理必须考虑生产环境的数据分布。
6.3 特征版本控制
随着业务发展,特征会不断迭代。我建立了特征版本控制系统:
features/ ├── v1/ │ ├── feature_pipeline.py │ └── metadata.json └── v2/ ├── feature_pipeline.py └── metadata.json这样能确保实验可复现,也方便回滚。我的经验是:特征工程也需要像代码一样管理。
7. 常见问题与解决方案
7.1 处理缺失值
实际数据中经常有缺失值,我的处理策略是:
- 数值特征:用中位数填充
- 类别特征:增加"未知"类别
- 序列特征:用零填充或屏蔽
df['age'].fillna(df['age'].median(), inplace=True) df['city'].fillna('unknown', inplace=True)7.2 处理新类别
��上经常出现训练时没见过的类别,我的解决方案是:
- 预留"未知"桶
- 使用哈希编码
- 建立类别准入机制
encoder.handle_unknown = 'ignore' # sklearn的设置7.3 特征漂移问题
数据分布随时间变化会导致特征漂移。我会:
- 监控特征统计量
- 定期重新训练编码器
- 使用滚动时间窗口训练
# 每月重新训练特征处理器 if datetime.now().day == 1: retrain_feature_pipeline()8. 特征处理工具推荐
8.1 开源工具
- Featuretools:自动化特征工程
- tsfresh:时间序列特征提取
- Category Encoders:丰富的类别编码方法
import featuretools as ft es = ft.EntitySet() es.add_dataframe(dataframe=df, dataframe_name='users') features, _ = ft.dfs(entityset=es, target_dataframe_name='users')8.2 云服务
- AWS SageMaker Feature Store
- Google Vertex AI Feature Store
- Databricks Feature Store
这些服务适合大规模特征管理,但要注意成本控制。
8.3 自建特征平台
对于成熟团队,我建议自建特征平台,包含:
- 特征注册中心
- 特征计算引擎
- 特征服务API
- 特征监控系统
我在上家公司主导开发的特征平台,将特征开发效率提升了60%。
9. 特征处理最佳实践
经过多个项目的实践,我总结了以下黄金法则:
- 简单有效:不要过度工程化,先用简单方法验证效果
- 可解释性:确保业务方理解关键特征的含义
- 自动化:建立自动化的特征流水线
- 监控:持续监控特征质量
- 迭代:定期回顾和优化特征集
在最近的一个推荐系统项目中,通过系统化的特征工程,我们在保持模型架构不变的情况下,将推荐准确率提升了15%。这再次验证了"数据和特征决定了模型的上限"这句话。