之前的模型局限
在个性化广告点击预测任务中存在的问题就是无法表达用户广泛的兴趣,因为这些模型在得到各个特征的embedding之后,就蛮力拼接了,然后就各种交叉等。这时候根本没有考虑之前用户历史行为商品具体是什么,究竟用户历史行为中的哪个会对当前的点击预测带来积极的作用。
DIN模型结构及原理
DIN模型的创新点或者解决的问题是使用了注意力机制来对用户的兴趣动态模拟, 模拟过程存在的前提是用户之前有大量的历史行为。
- 特征表示
经过编码后的特征数据,没有任何交互组合,没有做特征交叉。
- 基线模型
Embedding layer,Pooling & Concat layer和MLP
Embedding layer:
假设某个用户的weekday特征就是周五,化成one-hot编码的时候,就是[0,0,0,0,1,0,0]表示,这里如果再假设隐向量维度是D, 那么这个特征对应的embedding词典是一个
D
×
7
D\times7
D×7的一个矩阵(每一列代表一个embedding,7列正好7个embedding向量,对应周一到周日),那么该用户这个one-hot向量经过embedding层之后会得到一个
D
×
1
D\times1
D×1的向量,也就是周五对应的那个embedding,怎么算的,其实就是
e
m
b
e
d
d
i
n
g
矩
阵
∗
[
0
,
0
,
0
,
0
,
1
,
0
,
0
]
T
embedding矩阵* [0,0,0,0,1,0,0]^T
embedding矩阵∗[0,0,0,0,1,0,0]T 。其实也就是直接把embedding矩阵中one-hot向量为1的那个位置的embedding向量拿出来。 这样就得到了稀疏特征的稠密向量了。
pooling layer and Concat layer:
pooling layer先把用户历史行为embedding变成固定长度(统一长度),所以有了这个公式:
e
i
=
p
o
o
l
i
n
g
(
e
i
1
,
e
i
2
,
.
.
.
e
i
k
)
e_i=pooling(e_{i1}, e_{i2}, ...e_{ik})
ei=pooling(ei1,ei2,...eik) 这里的
e
i
j
e_{ij}
eij是用户历史行为的那些embedding。
i
i
i表示第
i
i
i个历史特征组(是历史行为,比如历史的商品id,历史的商品类别id等), 这里的
k
k
k表示对应历史特种组里面用户购买过的商品数量,也就是历史embedding的数量,看上面图里面的user behaviors系列,就是那个过程了。
Concat layer层的作用就是拼接了,就是把这所有的特征embedding向量,如果再有连续特征的话也算上,从特征维度拼接整合,作为MLP的输入。
-
MLP
普通的全连接,学习特征之间的各种交互。 -
Loss:
由于这里是点击率预测任务, 二分类的问题,所以这里的损失函数用的负的log对数似然: L = − 1 N ∑ ( x , y ) ∈ S ( y log p ( x ) + ( 1 − y ) log ( 1 − p ( x ) ) ) L=-\frac{1}{N} \sum_{(\boldsymbol{x}, y) \in \mathcal{S}}(y \log p(\boldsymbol{x})+(1-y) \log (1-p(\boldsymbol{x}))) L=−N1(x,y)∈S∑(ylogp(x)+(1−y)log(1−p(x)))
DIN模型架构
引入了一个新的local activation unit
输入是用户历史行为商品和当前的候选商品, 输出是它俩之间的相关性, 这个相关性相当于每个历史商品的权重,把这个权重与原来的历史行为embedding相乘求和就得到了用户的兴趣表示
v
U
(
A
)
\boldsymbol{v}{U}(A)
vU(A), 这个东西的计算公式如下:
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
\boldsymbol{v}{U}(A)=f\left(\boldsymbol{v}{A}, \boldsymbol{e}{1}, \boldsymbol{e}{2}, \ldots, \boldsymbol{e}{H}\right)=\sum_{j=1}^{H} a\left(\boldsymbol{e}{j}, \boldsymbol{v}{A}\right) \boldsymbol{e}{j}=\sum{j=1}^{H} \boldsymbol{w}{j} \boldsymbol{e}{j}
vU(A)=f(vA,e1,e2,…,eH)=j=1∑Ha(ej,vA)ej=∑j=1Hwjej 这里的
v
A
,
e
1
,
e
2
,
…
,
e
H
{\boldsymbol{v}{A}, \boldsymbol{e}{1}, \boldsymbol{e}{2}, \ldots, \boldsymbol{e}{H}}
vA,e1,e2,…,eH是用户
U
U
U的历史行为特征embedding,
v
A
v_{A}
vA表示的是候选广告
A
A
A的embedding向量,
a
(
e
j
,
v
A
)
=
w
j
a(e_j, v_A)=w_j
a(ej,vA)=wj表示的权重或者历史行为商品与当前广告
A
A
A的相关性程度。
a
(
⋅
)
a(\cdot)
a(⋅)表示的上面那个前馈神经网络,也就是那个所谓的注意力机制。
外积操作,是有利于模型相关性建模的显性知识。
DIN实现
VarlenSparse型特征(变长离散型):这个一般指的用户的历史行为特征,变长数据, 首先会进行padding操作成等长, 然后建立Input层接收输入,然后通过embedding层得到各自历史行为的embedding向量, 拿着这些向量与上面的候选商品embedding向量进入AttentionPoolingLayer去对这些历史行为特征加权合并,最后得到输出。
思考
att_hidden_units: 注意力层的隐藏单元个数.可以是一个列表或者元组,毕竟注意力层也是一个全连接的网络
mask = tf.cast(tf.not_equal(seq_inputs[:, :, 0], 0), dtype=tf.float32)
#(None, maxlen) 类型转换函数, 把seq_input中不等于0的值转成float32 #这个函数的作用就是每一行样本中, 不为0的值返回1, 为0的值返回0, 这样就把填充的那部分值都给标记了出来