实验和完整代码
完整代码实现和jupyter运行:https://github.com/Myolive-Lin/RecSys--deep-learning-recommendation-system/tree/main
引言
深度交叉网络(Deep Cross Network,简称 DCN)
是一种前沿的神经网络架构,专为大规模推荐系统中的点击率(CTR)预测等任务而设计,由(Wang et al. 2017)
等人提出。DCN 通过结合深度神经网络(DNN)的优势和显式特征交叉的能力,能够高效处理大规模数据集中的稀疏特征和密集特征。Deep cross Network的架构其实与Wide&Deep架构类似,区别在于Wide部分不同。
1.模型架构
本文将详细介绍 DCN 的关键组成部分,模型架构包括嵌入与堆叠层、交叉网络、深度网络以及组合层。
2.1 嵌入与堆叠层(Embedding and Stacking Layer)
在大规模推荐系统中,输入数据通常包含稀疏特征和密集特征。稀疏特征(如分类变量,例如“国家=美国”)通常被编码为独热向量。然而,独热编码会导致特征空间维度过高,尤其是在处理大型词汇表时。为了解决这一问题,DCN 采用嵌入技术,将这些稀疏的二进制特征转换为密集的低维实值向量。
嵌入过程
嵌入过程可以形式化为:
x embed , i = W embed , i x i x_{\text{embed},i} = W_{\text{embed},i} x_i xembed,i=Wembed,ixi
其中:
- x embed , i x_{\text{embed},i} xembed,i 是第 i 个分类特征的嵌入向量。
- x i x_i xi 是第 i 个类别的二进制输入。
- W embed , i ∈ R n e × n v W_{\text{embed},i} \in \mathbb{R}^{n_e \times n_v} Wembed,i∈Rne×nv 是嵌入矩阵,该矩阵在训练过程中学习得到。
- n e n_e ne和 n v n_v nv分别是嵌入维度和词汇表大小。
Stacking
嵌入完成后,将密集的嵌入向量与归一化的密集特征 x dense x_{\text{dense}} xdense 连接起来,形成一个单一的输入向量 x 0 x_0 x0 :
x 0 = [ x embed , 1 T , … , x embed , k T , x dense T ] T x_0 = [x_{\text{embed},1}^T, \dots, x_{\text{embed},k}^T, x_{\text{dense}}^T]^T x0=[xembed,1T,…,xembed,kT,xdenseT]T
这个堆叠后的向量 x_0 将被输入到网络的后续层中。
2.2 交叉网络(Cross Network)
交叉网络是 DCN 的核心,它能够以高效的方式实现显式的特征交叉。与传统的深度神经网络(DNN)隐式学习特征交互不同,交叉网络显式地建模特征交叉,使其在特征交互至关重要的任务中表现出色。
交叉层
交叉网络中的每一层遵循以下公式:
x l + 1 = x 0 x l T w l + b l + x l = f ( x l , w l , b l ) + x l x_{l+1} = x_0 x_l^T w_l + b_l + x_l = f(x_l, w_l, b_l) + x_l xl+1=x0xlTwl+bl+xl=f(xl,wl,bl)+xl
其中:
- x l , x l + 1 ∈ R d x_l, x_{l+1} \in \mathbb{R}^d xl,xl+1∈Rd 分别是第 l 层和第 l+1 层的输出。
- w l , b l ∈ R d w_l, b_l \in \mathbb{R}^d wl,bl∈Rd 是第 l 层的权重和偏置参数。
- 函数 f ( x l , w l , b l ) f(x_l, w_l, b_l) f(xl,wl,bl) 表示特征交叉操作。
计算方式可以参考下图:
交叉网络的独特结构使得特征交互的阶数随着网络深度的增加而增长。具体来说,一个 l l l层的交叉网络可以建模最高阶为 l + 1 l+1 l+1 的特征交互。
2.3 深度网络(Deep Network)
与交叉网络并行,DCN 还包含一个传统的深度网络,用于捕捉高度非线性的特征交互。深度网络是一个标准的全连接前馈神经网络,每一层定义如下:
h l + 1 = f ( W l h l + b l ) h_{l+1} = f(W_l h_l + b_l) hl+1=f(Wlhl+bl)
其中:
- h l ∈ R n l h_l \in \mathbb{R}^{n_l} hl∈Rnl 和 h l + 1 ∈ R n l + 1 h_{l+1}\in \mathbb{R}^{n_{l+1}} hl+1∈Rnl+1 分别是第 l 层和第 l+1 层的输出。
- W l ∈ R n l + 1 × n l W_l \in \mathbb{R}^{n_{l+1} \times n_l} Wl∈Rnl+1×nl 和 b l ∈ R n l + 1 b_l \in \mathbb{R}^{n_{l+1}} bl∈Rnl+1是第 l 层的权重和偏置参数。
- f ( ⋅ ) f(\cdot) f(⋅)是 ReLU 激活函数。
2.4 组合层(Combination Layer)
组合层将交叉网络和深度网络的输出进行拼接,并输入到标准的 logits 层进行最终预测。对于二分类问题,输出概率 p 的计算公式为:
p = σ ( [ x L 1 T , h L 2 T ] w logits ) p = \sigma([x_{L_1}^T, h_{L_2}^T] w_{\text{logits}}) p=σ([xL1T,hL2T]wlogits)
其中:
- x L 1 ∈ R d 和 h L 2 ∈ R m x_{L_1} \in \mathbb{R}^d 和 h_{L_2} \in \mathbb{R}^m xL1∈Rd和hL2∈Rm 分别是交叉网络和深度网络的输出。
- w logits ∈ R d + m w_{\text{logits}} \in \mathbb{R}^{d+m} wlogits∈Rd+m是组合层的权重向量。
- σ ( x ) \sigma(x) σ(x) 是 sigmoid 函数。
训练时使用的损失函数是带 L2 正则化的对数损失:
loss = − 1 N ∑ i = 1 N ( y i log ( p i ) + ( 1 − y i ) log ( 1 − p i ) ) + λ ∑ l ∥ w l ∥ 2 \text{loss} = -\frac{1}{N} \sum_{i=1}^N \left( y_i \log(p_i) + (1 - y_i) \log(1 - p_i) \right) + \lambda \sum_l \|w_l\|^2 loss=−N1i=1∑N(yilog(pi)+(1−yi)log(1−pi))+λl∑∥wl∥2
其中, y i y_i yi 是真实标签, p i p_i pi 是预测概率, N 是样本数量, λ \lambda λ 是正则化参数。
3.代码实现
class CrossLayer(nn.Module):
def __init__(self, input_dim):
super(CrossLayer, self).__init__()
self.weight = nn.Parameter(torch.Tensor(input_dim,1))
self.bias = nn.Parameter(torch.zeros(1))
# 初始化权重
nn.init.xavier_normal_(self.weight)
nn.init.zeros_(self.bias)
def forward(self, x0, x_l):
"""
x0: 初始输入张量,形状(batch_size, input_dim)
x_l: 当前层输入张量,形状(batch_size, input_dim)
返回:x_{l+1} = x0 * x_l^T * W_l + b_l + x_l
"""
x0 = x0.unsqueeze(2) # (batch_size, input_dim, 1)
x_l_t = x_l.unsqueeze(1) # (batch_size, 1, input_dim)
res = torch.bmm(x0, x_l_t) # (batch_size, input_dim, input_dim)
res = torch.matmul(res, self.weight) # (batch_size, input_dim, 1)
res = res.squeeze(2) # (batch_size, input_dim)
res = res + self.bias + x_l
return res
class CrossNetwork(nn.Module):
def __init__(self, input_dim, num_layers):
"""
Args:
input_dim: 输入特征维度
num_layers: 堆叠的CrossLayer层数
"""
super(CrossNetwork, self).__init__()
self.cross_layers = nn.ModuleList([
CrossLayer(input_dim) for _ in range(num_layers)
])
def forward(self,x):
"""
Args:
x: 输入张量,形状(batch_size, input_dim)
"""
x_l = x
for layer in self.cross_layers:
x_l = layer(x,x_l)
return x_l
class DeepCrossNetwork(nn.Module):
def __init__(self, num_deep_dim, cat_deep_dims, embedding_dim = 8,cross_num_layers=3, hidden_units = [128, 64],dropout = 0.2):
"""
Args:
num_deep_dim: Deep部分的数值型特征数量
cat_deep_dims: Deep部分的类别特征维度列表
embedding_dim: 嵌入维度
cross_num_layers: Cross网络的层数
hidden_units: 深度网络隐藏层维度列表
"""
super(DeepCrossNetwork, self).__init__()
self.num_categorical = len(cat_deep_dims)
self.num_continuous = num_deep_dim
self.embeddings = nn.ModuleList([
nn.Embedding(dim, embedding_dim)
for dim in cat_deep_dims
])
input_dim = num_deep_dim + len(cat_deep_dims) * embedding_dim
#Cross网络部分
self.cross = CrossNetwork(input_dim, cross_num_layers )
#Deep部分
dnn = []
deep_input_dim = input_dim
for hidden_dim in hidden_units:
dnn.append(nn.Linear(deep_input_dim, hidden_dim))
dnn.append(nn.BatchNorm1d(hidden_dim))
dnn.append(nn.ReLU())
dnn.append(nn.Dropout(dropout))
deep_input_dim = hidden_dim
self.dnn = nn.Sequential(*dnn)
# 最终输出层
self.combined_dim = input_dim + hidden_units[-1]
self.final_layer = nn.Linear(self.combined_dim, 1)
def forward(self, categorical_input, continuous_input):
"""
Args:
categorical_input: 类别型输入,形状(batch_size, num_categorical_features)
continuous_input: 数值型输入,形状(batch_size, num_continuous_features)
"""
# 类别特征嵌入处理
embedded = []
for i in range(self.num_categorical):
emd = self.embeddings[i](categorical_input[:, i])
embedded.append(emd)
embeded = torch.cat(embedded, dim=1) # 形状(batch_size, num_categorical_features * embedding_dim)
# 拼接数值型特征和嵌入特征
x0 = torch.cat([continuous_input, embeded], dim=1)
# 交叉网络和深度网络
cross_output = self.cross(x0)
deep_output = self.dnn(x0)
# 合并输出
combined_input = torch.cat([cross_output, deep_output], dim=1)
#最终输出
output = self.final_layer(combined_input)
return torch.sigmoid(output).squeeze(1) # 形状(batch_size,)
4. 总结
深度交叉网络(DCN)是一种强大的架构,它结合了显式特征交叉和深度学习的优势。通过高效地建模高阶特征交互并捕捉非线性模式,DCN 在点击率预测等任务中实现了顶尖的性能。其模块化的设计,包括嵌入与堆叠层、交叉网络、深度网络和组合层,使其在大规模应用中既灵活又可扩展。
Reference
- 王喆 《深度学习推荐系统》
- wang, R., Fu, B., Fu, G., & Wang, M. (2017). Deep & Cross Network for Ad Click Predictions. arXiv preprint arXiv:1708.05123.