深度推荐模型 -Day1

DeepCrossing

Embedding Layer

通常用于模型第一层,其目的是将所有索引标号(正整数)映射到致密的低维向量中,比如文本集[[4],[32],[67]]被映射为[[0.3,0.9,0.2],[-0.2,0.1,0,8],[0.1,0.3,0.9]]。本质上是用连续空间替代(准)离散空间,以增加空间利用率,减少不必要的参数。

优点:
来自深度学习中Embedding层有什么用?

  1. 使用One-hot 方法编码的向量会很高维也很稀疏。假设我们在做自然语言处理(NLP)中遇到了一个包含2000个词的字典,当时用One-hot编码时,每一个词会被一个包含2000个整数的向量来表示,其中1999个数字是0,要是我的字典再大一点的话这种方法的计算效率岂不是大打折扣?
  2. 使我们能可视化的了解词语之间的关系,不仅仅是词语,任何能通过嵌入层 Embedding 转换成向量的内容都可以这样做。相当于降维和特征提取,将稀疏矩阵组织称某种更易于分析的形式。

其在keras中的用法为:
keras.layers.Embedding(input_dim, output_dim, input_length=None)
其中的参数含义为:

  • input_dim: 词汇表大小,即此时所用的整个文档库所含的词数
  • output_dim: 输出的稠密词向量的维度,既想要用多少维表示词
  • input_length: 输入序列的长度,即输入了几个词

一个例子:
来自keras中文官方文档

model = Sequential()
model.add(Embedding(1000, 64, input_length=10))
# 模型将输入一个大小为 (batch, input_length) 的整数矩阵。
# 输入中最大的整数(即词索引)不应该大于 999 (词汇表大小)
# 现在 model.output_shape == (None, 10, 64),其中 None 是 batch 的维度。
input_array = np.random.randint(1000, size=(32, 10))
model.compile('rmsprop', 'mse')
output_array = model.predict(input_array)
assert output_array.shape == (32, 10, 64)

model.add(Embedding(1000, 64, input_length=10))表示文档库有1000个词,10个词为一组作为输入,我们希望用包含64个数的一维向量表示每个词。

这里的映射对应的尺寸变换为:(32,10,1) -> (32,10,64). 其中1是指索引标号(正整数),每个索引标号的范围为[1,1000],64是每个稠密向量的维度。

Stacking Layer

即把所有输入的特征连接起来,组成完整的包含全部特征的特征向量,在tf里用Concatnate层实现。特征既包含数值型特征,也包含经过Embedding的类别特征。

代码实现:

#将所有的dense特征拼接到一起
dense_dnn_list = list(dense_input_dict.values())
dense_dnn_inputs = Concatenate(axis=1)(dense_dnn_list) 
# B * n (n表示数值特征的数量,B是batch size)
# Concatenate是tf2的一个函数,`tf.keras.layers.Concatenate(axis=1)([x, y])`

# 因为需要将其与dense特征拼接到一起所以需要Flatten,不进行Flatten的Embedding层输出的维度为:B * 1 * dim(此处input_length=1)
sparse_dnn_list = concat_embedding_list(dnn_feature_columns, sparse_input_dict, embedding_layer_dict, flatten=True)
# concat_embedding_list是自定义的一个函数,用来实现Embedding层的flatten操作

sparse_dnn_inputs = Concatenate(axis=1)(sparse_dnn_list) 
# B * m * dim (m表示类别特征的数量,dim表示embedding的维度,如上一section的64)

# 将dense特征和Sparse特征拼接到一起
dnn_inputs = Concatenate(axis=1)([dense_dnn_inputs, sparse_dnn_inputs]) # B * (n + m * dim)

Multiple Residual Units Layer

DeepCrossing采用了残差网络进行的连接。通过多层残差网络对特征向量各个维度充分的交叉组合, 使得模型能够抓取更多的非线性特征和组合特征信息, 增加模型的表达能力。

Q:为什么要引入残差网络?

这个问题要从深度学习中神经网络的逐步加深说起,例如,在VGG中,卷积网络达到了19层,在GoogLeNet中,网络史无前例的达到了22层。**随着网络层数的增加,网络发生了退化(degradation)的现象:随着网络层数的增多,训练集loss逐渐下降,然后趋于饱和,当你再增加网络深度的话,训练集loss反而会增大。**因为存在梯度消失和梯度爆炸问题。注意这并不是过拟合,因为在过拟合中训练loss是一直减小的。

当网络退化时,浅层网络能够达到比深层网络更好的训练效果,这时如果我们把低层的特征传到高层,那么效果应该至少不比浅层的网络效果差。最主要的是残差块的存在解决了梯度消失和爆炸的问题。可以允许我们训练更深的网络,同时不会遇到退化现象。例如,一个VGG-100网络在第98层使用的是和VGG-16第14层一模一样的特征,那么VGG-100的效果应该会和VGG-16的效果相同。所以,我们可以在VGG-100的98层和14层之间添加一条直接映射(Identity Mapping)来达到此效果。

从信息论的角度讲,由于DPI(数据处理不等式)的存在,在前向传输的过程中,随着层数的加深,Feature Map包含的图像信息会逐层减少,而ResNet的直接映射的加入,保证了l+1层的网络一定比l层包含更多的图像信息。

# DNN残差块的定义
class ResidualBlock(Layer):
    def __init__(self, units): #units表示的是DNN隐藏层神经元数量
        super(ResidualBlock, self).__init__()
        self.units = units

    def build(self, input_shape):
        out_dim = input_shape[-1]
        #保证输入的维度和输出的维度一致才能进行残差连接
        self.dnn1 = Dense(self.units, activation='relu')
        self.dnn2 = Dense(out_dim, activation='relu')
    
    def call(self, inputs):
        x = inputs
        x = self.dnn1(x)
        x = self.dnn2(x)
        x = Activation('relu')(x + inputs) # 残差操作
        return x

Scoring Layer

就是叠加多个残差块,形成深度神经网络。对于CTR预估二分类问题,往往采用逻辑回归,激活函数用Sigmoid.

# block_nums表示DNN残差块的数量
def get_dnn_logits(dnn_inputs, block_nums=3):
    dnn_out = dnn_inputs
    for i in range(block_nums):
        dnn_out = ResidualBlock(64)(dnn_out)
    
    # 将dnn的输出转化成logits
    dnn_logits = Dense(1, activation='sigmoid')(dnn_out)
    return dnn_logits

损失函数

对数损失函数(交叉熵):
l o g l o s s = − 1 N ∑ 1 N ( y i l o g ( p i ) + ( 1 − y i ) l o g ( 1 − p i ) logloss=-\frac 1N\sum_1^N(y_ilog(p_i)+(1-y_i)log(1-p_i) logloss=N11N(yilog(pi)+(1yi)log(1pi)
其中 y i y_i yi表示真实的标签(点击或未点击), p i p_i pi表示Scoring Layer输出的结果。但是在实际应用中,根据不同的需求可以灵活替换为其他目标函数。

小结

DeepCrossing = Embedding layer + Residual layer + Logistic regression

DeepCrossing可以通过调整神经网络的深度进行特征之间的“深度交叉”,这也是Deep Crossing名称的由来。因为全联接网络本身可以看作是特征向量的各个维度之间互相关联。

最后附上论文原文:论文原文

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值