DIN!知识点啊朋友们!

2021-05-14 16:32:02 浏览数 (1)

作者:无敌最俊朗,蛇皮炼丹师

排版:炼丹笔记四品炼丹师

Deep Interest Network for Click-Through Rate Prediction(KDD2018)

背景

DIN是最早的一批对用户序列进行挖掘的文章,是目前处理用户行为数据不得不学习的基础内容了。它通过设计一个局部激活单元来自适应地学习用户对某个广告的历史行为的兴趣表示。这种表示向量在不同的广告中是不同的,大大提高了模型的表达能力。此外,我们还开发了两种技术:min-batch感知的正则以及数据自适应激活函数,它可以帮助训练具有数亿个参数的工业深层网络。

在本文之前,很多工作都还是基于embedding之后然后直接Concat,接入MLP进行模型的预测任务等,所以本篇文章的价值在当时是非常大的。下面我们一起结合论文学习一下!

网络基础框架

特征表示

工业的CTR任务,先通过encoding将特征转换到稀疏二元特征,第个特征组为,表示为特征组的维度,也就是说特征组中有个不同的id,为中第个元素,,向量中表示 one-hot编码, 表示multi-hot编码, 一个实例可以被表示为, 表示特征组,,为整个特征空间的维度,

underbrace{[0,0,0,0,1,0,0]}_{weekday = Friday} underbrace{[0,1]}_{gender = Female} underbrace{[0,...,1...,1,...0]}_{visited_cate_ids ={Bag,Book}} underbrace{[0,...,1,...,0]}_{ad_cate_id = Book}

基本模型(Embedding & MLP)

1.Embedding layer

因为我们的输入特征都是高维二元向量,embedding层将其转化为dense的表示,对于特征组,我们令表示第个embedding字典,其中表示维度为的embedding向量,

  • 如果为one-hot向量,其中第个元素, 那么的embedding表示就是一个向量;
  • 如果为multi-hot向量,其中第个元素, 那么的embedding表示就是;
2. Pooling layer and Concat Layer

因为多值特征会随着不为0的个数增长而变化,所以它的长度是不一样的,我们需要将其转化为固定的长度,此处我们使用pooling操作对其进行处理,

e_i = pooling(e_{i_1},e_{i_2},...,e_{i_k})

经常使用的pooling有sum pooling以及average pooling。

3. MLP层

当我们将所有的数据都拼接完成之后,下最后我们一般会连接一个全连接的MLP层,最后介入我们的Loss函数,

Loss = - frac{1}{N} sum_{(x,y) in mathcal{S}} (ylogp(x) (1-y)log(1-p(x)))

其中是大小为的训练集,是网络的实例特征,为对应的标签, 为网络的输出预测概率。

DIN网络框架

DIN的网络结构

和直接进行pooling操作等不同,此处,我们使用局部的activation来表征用户的兴趣。

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

其中是用户的行为embedding向量,是广告A的embedding向量,在不同的广告之间不一样,是一个前向网络。对应的code如下:

代码语言:javascript复制
def attention(queries, keys, keys_length):
    '''
    queries:     [B, H]
    keys:        [B, T, H]
    keys_length: [B]
    '''
    queries_hidden_units = queries.get_shape().as_list()[-1]
    queries = tf.tile(queries, [1, tf.shape(keys)[1]])
    queries = tf.reshape(queries, [-1, tf.shape(keys)[1], queries_hidden_units])
    
    din_all = tf.concat([queries, keys, queries-keys, queries*keys], axis=-1)
    
    ######## MLP
    d_layer_1_all = tf.layers.dense(din_all, 80, activation=tf.nn.sigmoid, name='f1_att', reuse=tf.AUTO_REUSE)
    d_layer_2_all = tf.layers.dense(d_layer_1_all, 40, activation=tf.nn.sigmoid, name='f2_att', reuse=tf.AUTO_REUSE)
    d_layer_3_all = tf.layers.dense(d_layer_2_all, 1, activation=None, name='f3_att', reuse=tf.AUTO_REUSE)
    d_layer_3_all = tf.reshape(d_layer_3_all, [-1, 1, tf.shape(keys)[1]])
    outputs = d_layer_3_all 
 
    # Mask
    key_masks = tf.sequence_mask(keys_length, tf.shape(keys)[1])   # [B, T]
    key_masks = tf.expand_dims(key_masks, 1) # [B, 1, T]
    paddings  = tf.ones_like(outputs) * (-2 ** 32   1)
    outputs   = tf.where(key_masks, outputs, paddings)  # [B, 1, T]

    # Scale
    outputs = outputs / (keys.get_shape().as_list()[-1] ** 0.5)

    # Activation
    outputs = tf.nn.softmax(outputs)  # [B, 1, T]

    # Weighted sum
    outputs = tf.matmul(outputs, keys)  # [B, 1, H]

    return outputs

训练技巧

1. Mini-Batch aware Regularization

实际训练中,直接使用传统的正则化技术,例如,是不practical的,本文引入一种高效的mini-batch aware的正则,我们令表示整个embedding字典的参数,表示为整个embedding字典的参数,是emebdding的向量,为特征空间的维度,

L_2(W) = ||W||^2_2 = sum_{j=1}^K ||w_j||_2^2 = sum_{(x,y) in mathcal{S}} sum_{j=1}^K frac{I(x_j neq 0)}{n_j}||w_j||^2_2

其中是第个embedding向量,表示是否有特征id,所以上面可以转换为:

L_2(W) = sum_{j=1}^K sum_{m=1}^B sum_{(x,y) in mathcal{B}_m} frac{I(x_j neq 0)}{n_j} ||w_j||_2^2

其中表示mini-batches的个数,表示第个mini-batch,我们令表示是否在mini-batch中有特征id,所以我们用近似表示上面的式子:

L_2(W) approx sum_{j=1}^K sum_{m=1}^B frac{alpha_{mj}}{n_j} ||w_j||_2^2

y于是我们得到一个近似的的正则,对于第个mini-batch,对应特征的embedding权重为:

w_j leftarrow w_j - eta left[ frac{1}{|mathcal{B}_m|} sum_{(x,y) in mathcal{B}_m} frac{partial L(p(x),y)}{partial w_j} lambda frac{alpha_{mj}}{nj}w_jright]
2. Data Adaptive Activation Function

1.PRELU

f(x)= left{ begin{array}{**lr**} s, text{if} s>0 & \ alpha s, text{if} sle 0\ end{array} right. =p(s) cdot s (1-p(s)) cdot alpha s

其中

2.Dice

f(s) = p(s) cdot s (1-p(s)) cdot alpha s, p(s) = frac{1}{1 e^{- frac{s-E[s]}{sqrt{Var[s] epsilon}}}}

Dice可以认为是PReLu的扩展,当和都为0的时候,Dice就变为来PReLU。

二者对应的code如下。

代码语言:javascript复制
def dice(_x, axis=-1, epsilon=0.000000001, name=''):
    with tf.variable_scope(name_or_scope='', reuse=tf.AUTO_REUSE):
    alphas = tf.get_variable('alpha' name, _x.get_shape()[-1],                                  
                         initializer=tf.constant_initializer(0.0),                         
                         dtype=tf.float32)
    beta = tf.get_variable('beta' name, _x.get_shape()[-1],                                  
                         initializer=tf.constant_initializer(0.0),                         
                         dtype=tf.float32)
    input_shape = list(_x.get_shape())

    reduction_axes = list(range(len(input_shape)))
    del reduction_axes[axis]
    broadcast_shape = [1] * len(input_shape)
    broadcast_shape[axis] = input_shape[axis]

    # case: train mode (uses stats of the current batch)
    mean = tf.reduce_mean(_x, axis=reduction_axes)
    brodcast_mean = tf.reshape(mean, broadcast_shape)
    std = tf.reduce_mean(tf.square(_x - brodcast_mean)   epsilon, axis=reduction_axes)
    std = tf.sqrt(std)
    brodcast_std = tf.reshape(std, broadcast_shape)
    x_normed = tf.layers.batch_normalization(_x, center=False, scale=False, name=name, reuse=tf.AUTO_REUSE)
    # x_normed = (_x - brodcast_mean) / (brodcast_std   epsilon)
    x_p = tf.sigmoid(beta * x_normed)

    return alphas * (1.0 - x_p) * _x   x_p * _x

def parametric_relu(_x):
    with tf.variable_scope(name_or_scope='', reuse=tf.AUTO_REUSE):
    alphas = tf.get_variable('alpha', _x.get_shape()[-1],
                         initializer=tf.constant_initializer(0.0),
                         dtype=tf.float32)
    pos = tf.nn.relu(_x)
    neg = alphas * (_x - abs(_x)) * 0.5

    return pos   neg

实验

1. 效果比较

  • DIN的效果是最好的;
  • DIN加入Dice后效果更好

2. 正则比较

  • 本文提出的正则化方案取得了显著的效果

3. Alibaba数据集比较

  • 在Alibaba数据集上,DIN MBA正则 Dice取得了显著的效果;

小结

本文主要针对电子商务行业展示广告场景中用户行为数据丰富的场景进行CTR预测建模。在传统的深度CTR模型中,固定长度表示的使用是捕捉用户兴趣多样性的瓶颈。为了提高模型的表达能力,设计了一种新的方法DIN来激活相关的用户行为,获得用户兴趣的自适应表示向量,并引入了两种新的技术来帮助训练工业深层网络,进一步提高DIN的性能。它们可以很容易地推广到其他工业深度学习任务。

本文是较早将Attention用于序列挖掘的文章,目前可以作为是Baseline,序列挖掘必知的基础了,非常经典,也会经常当作基础被问到。

参考文献

  1. Deep Interest Network for Click-Through Rate Prediction:https://arxiv.org/pdf/1706.06978.pdf
  2. https://github.com/zhougr1993/DeepInterestNetwork

0 人点赞