基于PyTorch的Wide&Deep算法实现

一、数据预处理与特征工程

import torch
import torch.nn as nn
from torch.utils.data import DataLoader, Dataset

class WideDeepDataset(Dataset):
    def __init__(self, data, categorical_cols, continuous_cols, target_col):
        self.categorical = data[categorical_cols].values
        self.continuous = data[continuous_cols].values
        self.target = data[target_col].values
        
    def __len__(self):
        return len(self.target)
    
    def __getitem__(self, idx):
        return torch.tensor(self.categorical[idx], dtype=torch.long), \
               torch.tensor(self.continuous[idx], dtype=torch.float32), \
               torch.tensor(self.target[idx], dtype=torch.float32)

关键点​​:

  1. 分离类别特征(如用户ID、物品ID)和连续特征(如价格、评分)
  2. 使用Dataset封装数据加载逻辑,支持批量处理

二、模型架构实现

class WideAndDeep(nn.Module):
    def __init__(self, cat_dims, emb_dims, hidden_units, num_wide_features):
        super().__init__()
        
        # Wide部分:线性模型 + 交叉特征
        self.wide = nn.Linear(num_wide_features, 1)
        
        # Deep部分:Embedding层 + MLP
        self.embeddings = nn.ModuleList([
            nn.Embedding(cat_dim, emb_dim) for cat_dim, emb_dim in zip(cat_dims, emb_dims)
        ])
        
        # 计算Embedding总维度
        total_emb_dim = sum(emb_dims)
        self.deep = nn.Sequential(
            nn.Linear(total_emb_dim + continuous_cols.shape[1], hidden_units[0]),
            nn.ReLU(),
            nn.Linear(hidden_units[0], hidden_units[1]),
            nn.ReLU(),
            nn.Linear(hidden_units[1], 1)
        )
        
    def forward(self, categorical_feats, continuous_feats):
        # Wide部分:直接线性组合
        wide_out = self.wide(categorical_feats)
        
        # Deep部分:Embedding + MLP
        embedded_feats = [emb(feats) for emb, feats in zip(self.embeddings, categorical_feats)]
        embedded_feats = torch.cat(embedded_feats, dim=1)
        deep_input = torch.cat([embedded_feats, continuous_feats], dim=1)
        deep_out = self.deep(deep_input)
        
        # 联合输出
        out = 0.5 * wide_out + 0.5 * deep_out  # 权重可调节
        return torch.sigmoid(out)

​关键代码解读​​:

  1. ​Wide部分​​:

    • 使用线性层直接学习特征交叉(如AND(gender=female,language=en)
    • 输入为经过One-Hot编码的交叉特征向量
  2. ​Deep部分​​:

    • nn.Embedding层将离散特征映射为低维稠密向量
    • 多层全连接网络(MLP)学习高阶非线性关系
    • 与Wide部分共享输入特征
  3. ​联合训练​​:输出层加权融合(权重可调),通过Sigmoid激活得到CTR预测

三、训练流程实现

# 超参数设置
cat_dims = [1000, 500]  # 各分类特征的类别数
emb_dims = [64, 32]     # 各分类特征的Embedding维度
hidden_units = [128, 64]  # MLP隐藏层单元数
num_wide_features = 10  # Wide部分的特征数量

# 初始化模型
model = WideAndDeep(cat_dims, emb_dims, hidden_units, num_wide_features)

# 损失函数与优化器
criterion = nn.BCELoss()  # 二分类交叉熵
optimizer = torch.optim.AdamW(model.parameters(), lr=0.001, weight_decay=1e-5)

# 训练循环示例
for epoch in range(10):
    for cat_feats, cont_feats, labels in DataLoader(dataset, batch_size=256):
        preds = model(cat_feats, cont_feats)
        loss = criterion(preds, labels)
        
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

关键点​​:

  1. 使用BCELoss处理二分类问题(点击率预测)
  2. AdamW优化器结合权重衰减防止过拟合
  3. 特征输入需预处理为:
    • 类别特征:整数编码(如user_id=123→索引)
    • 连续特征:标准化/归一化

四、核心设计解析

  1. ​记忆与泛化的平衡​​:

    • Wide部分通过人工设计的交叉特征(如user_age * item_category)直接记忆重要规则
    • Deep部分通过Embedding自动学习特征表示,泛化新特征组合
  2. ​特征处理策略​​:

    • 稀疏特征:使用Embedding层降维(如用户ID映射到64维向量)
    • 稠密特征:直接输入线性层或归一化后处理
  3. ​联合训练优势​​:

    • 相比Ensemble,参数共享减少计算量
    • 端到端训练避免误差累积

五、应用场景优化建议

  1. ​特征工程​​:

    • Wide部分加入高频交叉特征(如gender * occupation
    • Deep部分对长尾类别进行分桶处理
  2. ​正则化​

# 在Deep部分添加Dropout
self.deep = nn.Sequential(
    nn.Linear(...),
    nn.ReLU(),
    nn.Dropout(0.5),
    ...
)
  1. ​线上服务​​:

    • 使用torchscript导出模型
    • 通过Redis缓存高频特征的Embedding
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值