一、概念

        DCN(Deep & Cross Network)模型是一种常用于推荐系统的深度学习模型,出自谷歌的论文《Deep & Cross Network for Ad Click Predictions》,旨在有效地捕捉特征之间的交叉关系。DCN模型结合了深度网络和交叉网络两种结构,能够同时学习特征的高阶交叉和非线性组合,常用于推荐系统的精排阶段

        DCN模型的核心优势在于其能够显式地学习特征之间的交互关系,同时结合深度网络的强大表达能力,适用于需要处理复杂特征交互的场景。无论是推荐系统(个性化推荐)、广告系统(CTR)、搜索排序(相关度)还是用户行为预测,DCN都能够通过高效的特征交互学习,显著提升模型的预测性能。

二、原理

        DCN模型由两个主要部分组成:

  • Cross Network(交叉网络):交叉网络通过逐层交叉操作来捕捉特征之间的交叉关系。每一层的输出是当前层输入与原始输入的交叉组合,能够有效地学习特征的高阶交叉。
  • Deep Network(深度网络):深度网络是一个典型的MLP,负责学习特征的非线性组合。

        目前,DCN已经发展出了两个版本:

1、DCN-v1

        在这一版的DCN模型中,每个交叉层的公式为:

x_{l+1} = x_{0}x_{l}^{T}w_{l}+b_{l}+x_{l}

        其中,x_{0}是底部交叉层的输入,由各种类别特征的嵌入和稠密特征拼接而成;x_{l},x_{l+1}分别是第l个交叉层的输入和输出;w_{l},b_{l}是第l个交叉层的权重和偏置,都是d维的可学习参数。对于一个包含L个交叉层的交叉网络,其最终结果包含了原始输入x_{0}中所有元素之间小于或者等于 L+1 阶的交叉。

2、DCN-v2

        在DCN-v1中,每层要学习的参数只有w_{l},b_{l},参数数量有限,限制了模型的表达能力。因此,DCN-v2用一个d*d的矩阵w_{l}代替了DCN-v1中的d维向量w_{l}

x_{l+1} = X_{0} \odot (W_{l}x_{l}+b_{l})+x_{l}

        其中,x_{0}是原始输入,x_{l}是第l层的输入,长度都为d。而在实际的应用场景中,原始输入的维度d一般都很大,可以是上千维,这时候w_{l}作为一个d*d的矩阵,会给模型造成巨大的计算压力。因此,DCN-v2的作者提出了使用两个小矩阵对w_{l}进行分解的策略,即W_{l} = U_{l}V_{l}^{T},这两个小矩阵的维度都为d*r(r<<d),从而将参数量从d²减少为2*d*r,实际上就是低秩矩阵分解。

3、融入DNN

        为了进一步提升DCN网络的性能,一般来说我们会显式地融合DCN和DNN,通常有两种形式:一种是原始特征先过DCN,再过DNN,最后输出;另一种是原始特征分别经过DCN和DNN,然后合并两者的输出,再使用一个全连接层计算最终的预测结果

三、python实现

        以下是一个结合电商领域的知识构建数据集并实现DCN(Deep & Cross Network)模型的完整代码示例。我们构建一个模拟的电商数据集,包含以下字段:

  • 用户特征:年龄、性别、用户等级
  • 商品特征:商品类别、价格区间
  • 行为特征:用户点击、购买记录

        模型同时预测用户的点击和购买行为。

import torch
import torch.nn as nn
import torch.optim as optim
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder, StandardScaler

# 构建模拟电商数据集
def create_dataset(num_samples=1000):
    np.random.seed(42)
    data = {
        "user_age": np.random.randint(18, 60, num_samples),
        "user_gender": np.random.choice(["M", "F"], num_samples),
        "user_level": np.random.choice(["low", "medium", "high"], num_samples),
        "item_category": np.random.choice(["electronics", "clothing", "home"], num_samples),
        "item_price": np.random.uniform(10, 1000, num_samples),
        "clicked": np.random.choice([0, 1], num_samples),
        "purchased": np.random.choice([0, 1], num_samples),
    }
    return pd.DataFrame(data)

# 数据预处理
def preprocess_data(df):
    # 编码分类特征
    label_encoders = {}
    for col in ["user_gender", "user_level", "item_category"]:
        le = LabelEncoder()
        df[col] = le.fit_transform(df[col])
        label_encoders[col] = le
    
    # 标准化数值特征
    scaler = StandardScaler()
    df["user_age"] = scaler.fit_transform(df[["user_age"]])
    df["item_price"] = scaler.fit_transform(df[["item_price"]])
    
    # 特征和标签
    features = df[["user_age", "user_gender", "user_level", "item_category", "item_price"]].values
    labels = df[["clicked", "purchased"]].values
    return features, labels

# 构建DCN模型
class DCN(nn.Module):
    def __init__(self, input_dim, cross_layers, deep_layers):
        super(DCN, self).__init__()
        self.input_dim = input_dim
        
        # Cross Network
        self.cross_layers = nn.ModuleList([nn.Linear(input_dim, input_dim) for _ in range(cross_layers)])
        
        # Deep Network
        deep_modules = []
        for i in range(len(deep_layers) - 1):
            deep_modules.append(nn.Linear(deep_layers[i], deep_layers[i+1]))
            deep_modules.append(nn.ReLU())
        self.deep_network = nn.Sequential(*deep_modules)
        
        # Final output layer
        self.output_layer = nn.Linear(deep_layers[-1] + input_dim, 2)  # 2个输出:点击和购买
    
    def forward(self, x):
        # Cross Network
        cross_out = x
        for layer in self.cross_layers:
            cross_out = layer(cross_out) + cross_out * x
        
        # Deep Network
        deep_out = self.deep_network(x)
        
        # Concatenate Cross and Deep outputs
        combined_out = torch.cat([cross_out, deep_out], dim=1)
        
        # Final output
        return self.output_layer(combined_out)

# 主程序
if __name__ == "__main__":
    # 构建数据集
    df = create_dataset()
    features, labels = preprocess_data(df)
    
    # 划分训练集和测试集
    X_train, X_test, y_train, y_test = train_test_split(features, labels, test_size=0.2, random_state=42)
    
    # 转换为Tensor
    X_train = torch.tensor(X_train, dtype=torch.float32)
    X_test = torch.tensor(X_test, dtype=torch.float32)
    y_train = torch.tensor(y_train, dtype=torch.float32)
    y_test = torch.tensor(y_test, dtype=torch.float32)
    
    # 模型参数
    input_dim = X_train.shape[1]
    cross_layers = 3
    deep_layers = [input_dim, 64, 32]
    
    # 初始化模型
    model = DCN(input_dim, cross_layers, deep_layers)
    criterion = nn.BCEWithLogitsLoss()
    optimizer = optim.Adam(model.parameters(), lr=0.001)
    
    # 训练模型
    epochs = 20
    for epoch in range(epochs):
        model.train()
        optimizer.zero_grad()
        outputs = model(X_train)
        loss = criterion(outputs, y_train)
        loss.backward()
        optimizer.step()
        
        print(f"Epoch {epoch+1}/{epochs}, Loss: {loss.item():.4f}")
    
    # 测试模型
    model.eval()
    with torch.no_grad():
        test_outputs = model(X_test)
        test_loss = criterion(test_outputs, y_test)
        print(f"Test Loss: {test_loss.item():.4f}")
Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐