[CTR模型] DIN(Deep Interest Network)模型解读与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)+(1y)log(1p(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=1Ha(ej,vA)ej=j=1Hwjej
其中, { 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 regularizer

为了避免过拟合,作者引入一种mini-batch aware regularizer:它只计算出现在每个小批中的稀疏特征参数的l2 范数,未出现的特征则不进行计算。

CTR网络大大部分参数来自于Embedding,假定嵌入向量的维度是D,特征空间的个数为K,则Embedding过程的参数 W ∈ R D × K W \in \mathcal R^{D\times K} WRD×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)=W22=j=1Kwj22=(x,y)Sj=1KnjI(xj=0)wj22
其中, w j ∈ R D \mathbf w_j \in \mathbf R^D wjRD 是一个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=1Km=1B(x,y)BmnjI(xj=0)wj22
其中,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=1Km=1Bnjαmjwj22
其中, α 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…

Dice激活函数

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αsifs0=p(s)s+(1p(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[s]}{\sqrt{V a r[s]+\epsilon}}}} f(s)=p(s)s+(1p(s))αsp(s)=1+eVar[s]+ϵ sE[s]1
其中 E [ s ] , V a r [ s ] E[s], Var[s] E[s],Var[s] 分别是每个 mini-batch 数据的均值与方差, ϵ \epsilon ϵ 1 0 − 8 10^{-8} 108 。函数图像如下:

在这里插入图片描述

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=1nwii=1nwi×AUCi=i=1nimpii=1nimpi×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模型,安装方式如下:

pip install deepctr[gpu]

使用包括两个部分

(1)处理数据


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)训练模型

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

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值