文章目录
- 基本想法
- 基准模型
- DIN模型
-
- 基本原理
- 训练技巧
-
- mini-batch aware
- 激活函数
- GAUC 评估指标
- Deepctr实现
基本想法
首先说说DIN(Deep Interest Network)到底在干嘛,DIN主基本想法是:利用用户的历史行为序列(下单,点击等)提高推荐物品的点击率。
论文中有这样一幅图:

图中显示了一个女生的行为序列,被推荐物品是一个女大衣。传统的推荐物品的CTR计算方法是不会区别对待历史行为中的物品与被推荐物品的相关度,也就是下文提到的基础模型。DIN最大的特点是在计算推荐物品的CTR时,考虑历史序列中的物品对当前推荐物品的影响(图中的进度条),也就是Attention机制。这也是阿里将attention机制引入推荐模型的动机。
论文显示介绍了一个通用的基准模型,然后在加入attention机制,得到DIN模型
基准模型
基础模型共享一个类似的嵌入和多层感知机的范式,如下图所示。它由几个部分组成:

(1)Embedding layer:嵌入层,将输入(高维二进制向量)转换成低维稠密表示。
(2)Pooling layer and Concat layer:常见的池化操作有:sum pooling and average pooling,对嵌入向量列表应用求和/平均操作。因为用户的行为序列一般是不同的,因此可以对所有的Embedding结果进行sum pooling,得到一个固定大小的向量,作为全连接层的输入。
嵌入和池化层将原始的稀疏特征映射到多个固定的长度表示向量。然后将所有向量连接在一起获得实例的整体表示向量。
(3)MLP:多层感知机,完全连接层用于自动学习特征的组合。
(4)Loss:基本模型中使用的目标函数是负对数似然函数,定义如下:
L
=
?
1
N
∑
(
x
,
y
)
∈
S
(
y
l
o
g
p
(
x
)
+
(
1
?
y
)
l
o
g
(
1
?
p
(
x
)
)
)
L = - \frac{1}{N} \sum_{(x,y) \in S}(ylogp(x)+(1-y)log(1-p(x)))
L=?N1?(x,y)∈S∑?(ylogp(x)+(1?y)log(1?p(x)))
DIN模型
基本原理

与基本模型相比,DIN引入了一种新颖的Activation Unit,保留其他结构不变,与base模型基本相同。Activation Unit可以自适应地计算在给定广告A 的情况下用户表示向量
v
u
\mathbf v_u
vu?
v
U
(
A
)
=
f
(
v
A
,
e
1
,
e
2
,
.
.
.
,
e
H
)
=
∑
j
=
1
H
a
(
e
j
,
v
A
)
e
j
=
∑
j
=
1
H
w
j
e
j
v_U(A) = f(v_A,e_1,e_2,...,e_H)=\sum_{j=1}^Ha(e_j,v_A)e_j=\sum_{j=1}^Hw_je_j
vU?(A)=f(vA?,e1?,e2?,...,eH?)=j=1∑H?a(ej?,vA?)ej?=j=1∑H?wj?ej?
其中,
{
e
1
,
e
2
,
…
,
e
H
}
\{e_1,e_2,\dots,e_H\}
{e1?,e2?,…,eH?} 是用户u的历史行为嵌入向量(历史序列长度为H),a(.)是Activation Unit的输出权重,此处的权重不需要进行softmax归一化,理由如下:
在t恤和手机两个候选广告中,t恤激活了大部分属于衣服的历史行为,衣服可能会比手机获得更大的权重值(更高的兴趣强度)。传统的注意力方法通过对a(·)的输出进行softmax归一化而失去了数值尺度上的分辨率。
v
U
v_U
vU?是代表用户行为的embedding向量,
v
A
v_A
vA? 是候选广告商品的embedding向量,
e
i
e_i
ei?是用户u的第i次行为的embedding向量,没有引入注意力机制的基准模型中,
v
U
v_U
vU?是
e
i
e_i
ei?的加和,在DIN中,通过将
v
A
v_A
vA?与
e
i
e_i
ei?输入Activation Unit 输出可以衡量二者相关度的权重,然后对
e
i
e_i
ei?加权求和得到代表用户行为的embedding向量
v
U
v_U
vU?。
Activation Unit本质是求被推荐的广告与历史行为序列中的item的相似度。
这是这篇论文70%的价值所在。
训练技巧
这部分是论文的剩余30%价值主要包括:
(1)引入Adaptive的正则化方法:mini-batch aware
(2)用Dice方法替代经典的PReLU激活函数
(3)用GAUC这个离线metric替代AUC
mini-batch aware
为了避免过拟合,作者引入一种mini-batch aware regularizer:它只计算出现在每个小批中的稀疏特征参数的l2 范数,未出现的特征则不进行计算。
CTR网络大大部分参数来自于Embedding,假定嵌入向量的维度是D,特征空间的个数为K,则Embedding过程的参数
W
∈
R
D
×
K
W \in \mathcal R^{D\times K}
W∈RD×K。
传统的L2正则化如下:
L
2
(
W
)
=
∣
∣
W
∣
∣
2
2
=
∑
j
=
1
K
∣
∣
w
j
∣
∣
2
2
=
∑
(
x
,
y
)
∈
S
∑
j
=
1
K
I
(
x
j
≠
0
)
n
j
∣
∣
w
j
∣
∣
2
2
L_2(W) = ||W||_2^2 = \sum_{j=1}^K ||w_j||^2_2 = \sum_{(x,y) \in S}\sum_{j=1}^K \frac{I(x_j \ne 0)}{n_j} ||w_j||_2^2
L2?(W)=∣∣W∣∣22?=j=1∑K?∣∣wj?∣∣22?=(x,y)∈S∑?j=1∑K?nj?I(xj??=0)?∣∣wj?∣∣22?
其中,
w
j
∈
R
D
\mathbf w_j \in \mathbf R^D
wj?∈RD 是一个D维的向量(特征 j 嵌入到D维),
I
(
x
j
≠
0
)
I(x_j \ne 0)
I(xj??=0)表示当前数据是否拥有特征
j
j
j;
n
j
n_j
nj? 表示在所有数据中特征
j
j
j出现的次数。
注:在深度CTR领域,性别、学历等称为field,性别包含男、女两个取值,即:为两个不同的特征。
传统的L2正则化需要在每一个mini-batch的训练过程中更新所有的参数,这个过程计算量十分大。
在mini-batch aware regularizer中的L2正则化如下:
L
2
(
W
)
=
∑
j
=
1
K
∑
m
=
1
B
∑
(
x
,
y
)
∈
B
m
I
(
x
j
≠
0
)
n
j
∣
∣
w
j
∣
∣
2
2
L_2(W) = \sum_{j=1}^K \sum_{m=1}^B \sum_{(x,y) \in B_m}\frac{I(x_j \ne 0)}{n_j} ||w_j||_2^2
L2?(W)=j=1∑K?m=1∑B?(x,y)∈Bm?∑?nj?I(xj??=0)?∣∣wj?∣∣22?
其中,B是数据集的mini-batches的个数,
B
m
B_m
Bm?表示第m个mini-batch。
对上述公式继续简化:
L
2
(
W
)
≈
∑
j
=
1
K
∑
m
=
1
B
α
m
j
n
j
∣
∣
w
j
∣
∣
2
2
L_2(W) \approx \sum_{j=1}^K \sum_{m=1}^B \frac{\alpha_{mj}}{n_j}||w_j||_2^2
L2?(W)≈j=1∑K?m=1∑B?nj?αmj??∣∣wj?∣∣22?
其中,
α
m
j
\alpha_{mj}
αmj? 表示特征 j 是否出现在 mini-batch 样本 B 中,若没有出现,
α
m
j
=
0
\alpha_{mj}=0
αmj?=0,则对应参数不进行更新,极大减小计算量。
n
j
n_j
nj? 表示样本 j 在 B 中的出现次数,
w
j
w_j
wj? 则是第 j 个嵌入向量。整个公式的核心思想是出现的频率越大,正则化的强度越大。
所以,第
m
m
m个mini-batch对第
j
j
j个特征的嵌入向量
w
j
\mathbf w_j
wj?的更新过程如下:
KaTeX parse error: Undefined control sequence: \part at position 92: …\in B_m} \frac{\?p?a?r?t? ?L(p(x),y)}{\par…
激活函数
PReLU 可以看作是 ReLU 的改版,计算方法为:
f
(
s
)
=
{
s
????
i
f
s
>
0
α
s
i
f
s
≤
0
=
p
(
s
)
?
s
+
(
1
?
p
(
s
)
)
?
α
s
\begin{aligned} f(s) & =\left\{ \begin{array}{l} s \;\;\qquad if\quad s>0 \\ \alpha s \qquad if\quad s \le 0 \end{array} \right. \\ & = p(s) \cdot s + (1-p(s))\cdot\alpha s \end{aligned}
f(s)?={sifs>0αsifs≤0?=p(s)?s+(1?p(s))?αs?
无论是 ReLU 或者是 PReLU 突变点都是0。而论文认为突变点的选择应该依赖于数据,于是基于 PReLU 提出了 Dice 激活函数:
f
(
s
)
=
p
(
s
)
?
s
+
(
1
?
p
(
s
)
)
?
α
s
p
(
s
)
=
1
1
+
e
?
s
?
E
[
s
]
V
a
r
[
s
]
+
?
f(s)=p(s) \cdot s+(1-p(s)) \cdot \alpha s\\ p(s)=\frac{1}{1+e^{-\frac{s-E▼显示}{\sqrt{V a r▼显示+\epsilon}}}}
f(s)=p(s)?s+(1?p(s))?αsp(s)=1+e?Var▼显示+?
E
[
s
]
,
V
a
r
[
s
]
E▼显示, Var▼显示
E▼显示,Var▼显示 分别是每个 mini-batch 数据的均值与方差,
?
\epsilon
? 取
1
0
?
8
10^{-8}
10?8 。函数图像如下:

GAUC 评估指标
GAUC 是 AUC 的加权平均:
G
A
U
C
=
∑
i
=
1
n
w
i
×
A
U
C
i
∑
i
=
1
n
w
i
=
∑
i
=
1
n
i
m
p
i
×
A
U
C
i
∑
i
=
1
n
i
m
p
i
\mathrm{GAUC}=\frac{\sum_{i=1}^{n} w_{i} \times \mathrm{AUC}_{i}}{\sum_{i=1}^{n} w_{i}}=\frac{\sum_{i=1}^{n} \mathrm{imp}_{i} \times \mathrm{AUC}_{i}}{\sum_{i=1}^{n} \mathrm{imp}_{i}}
GAUC=∑i=1n?wi?∑i=1n?wi?×AUCi??=∑i=1n?impi?∑i=1n?impi?×AUCi??
其中:n 是用户的数量,
A
U
C
i
AUC_i
AUCi? 表示用户
i
i
i 所有样本的 AUC,
i
m
p
i
imp_i
impi? 是用户
i
i
i 所有样本的个数。AUC 是考虑所有样本的排名,而实际上,我们只要关注给每个用户推荐的广告的排序,因此GAUC更具有指导意义。
Deepctr实现
模型的代码实现较为复杂,具体细节可以参考我的github,以下是使用deepctr实现的DIN模型。
首先要安装deepctr模型,安装方式如下:
1 | pip install deepctr[gpu] |
使用包括两个部分
(1)处理数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | def get_xy_fd(): # 初始化虚拟数据 # 行为序列名称,一般包括item_id和item对应的cate_id behavior_feature_list = ["item_id", "cate_id"] # user_id uid = np.array([0, 1, 2]) # user 性别特征 ugender = np.array([0, 1, 0]) # user 的评分特征 pay_score = np.array([0.1, 0.2, 0.3]) # 被推荐的物品的id及其所属类别 item_id = np.array([1, 2, 3]) # 0 is mask value cate_id = np.array([1, 2, 2]) # 0 is mask value # 用户的历史行为序列,假设长度为4,长度不足4的用0填充 hist_item_id = np.array([[1, 2, 3, 0], [3, 2, 1, 0], [1, 2, 0, 0]]) hist_cate_id = np.array([[1, 2, 2, 0], [2, 2, 1, 0], [1, 2, 0, 0]]) # 对特征进行嵌入 # SparseFeat(name, vocabulary_size, embedding_dim) # eg 将3个user分别嵌入到10维 feature_columns = [SparseFeat('user',3,embedding_dim=10), SparseFeat('gender', 2,embedding_dim=4), SparseFeat('item_id', 3,embedding_dim=8), SparseFeat('cate_id', 2,embedding_dim=4), DenseFeat('pay_score', 1)] # 处理历史序列数据 # VarLenSparseFeat(sparsefeat, maxlen, combiner, length_name, weight_name,weight_norm) # vocabulary_size = 原始的行为种类个数+1,对于长度不足4的部分会用0来填充,因此 vocabulary_size 应该在原来的基础上 + 1(新增一种行为0) feature_columns += [VarLenSparseFeat(SparseFeat('hist_item_id', vocabulary_size=3 + 1,embedding_dim=8,embedding_name='item_id'), maxlen=4), VarLenSparseFeat(SparseFeat('hist_cate_id', 2 + 1,embedding_dim=4, embedding_name='cate_id'), maxlen=4)] # 构造特征字典 feature_dict = {<!-- -->'user': uid, 'gender': ugender, 'item_id': item_id, 'cate_id': cate_id, 'hist_item_id': hist_item_id, 'hist_cate_id': hist_cate_id, 'pay_score': pay_score} # 构造输入(x,y) x = {<!-- -->name:feature_dict[name] for name in get_feature_names(feature_columns)} y = np.array([1, 0, 1]) return x, y, feature_columns, behavior_feature_list |
(2)训练模型
1 2 3 4 5 6 | if __name__ == "__main__": x, y, feature_columns, behavior_feature_list = get_xy_fd() model = DIN(feature_columns, behavior_feature_list) model.compile('adam', 'binary_crossentropy', metrics=['binary_crossentropy']) history = model.fit(x, y, verbose=1, epochs=10, validation_split=0.5) |
总结思考:
Attention机制什么?(知识)
本质是加权求和,关键是“如何获得权重”,DIN通过计算被推荐商品与历史行为序列中的商品的关系来作为权重值,也就是论文中的Activation Unit部分。
参考:
推荐系统中的注意力机制——阿里深度兴趣网络(DIN)
CTR深度学习模型之 DIN(Deep Interest Network) 的理解与例子
Deep Interest and Evolution Network for CTR