前言
今天主要通过两篇论文介绍如何将CNN应用在传统的结构化数据预测任务中,本文尽量以精简的语言说明主要问题,并提供代码实现和运行demo,细节问题请参阅论文。
- CIKM‘05 《A Convolutional Click Prediction Model》
- WWW’19《Feature Generation by Convolutional Neural Network for Click-Through Rate Prediction》
CNN在计算机视觉领域占据着主导地位,在自然语言处理领域也有广泛的应用。基于点击率预测任务和自然语言处理中一些任务的相似性(大规模稀疏特征),NLP的一些方法和CTR预测任务的方法其实也是可以互通的。
A Convolutional Click Prediction Model
模型结构
主要思想
通过一个(width, 1)
的kernel进行对特征的embedding矩阵进行二维卷积,其中width
表示的每次对连续的width
个特征进行卷积运算,之后使用一个Flexible pooling
机制进行池化操作进行特征聚合和压缩表示,堆叠若干层后将得到特征矩阵作为MLP的输入,得到最终的预测结果。
这里解释两个问题
- 为什么强调是连续的
width
个特征进行卷积
-
我们都知道CNN之所以在CV领域大放异彩是由于其具有如下特性
- 参数共享
通常一个特征检测子(如边缘检测)在图像某一部位有用也在其他部位生效。 - 稀疏连接
每一层的输出只依赖于前一层一小部分的输入
- 参数共享
-
在NLP任务中由于语句天然存在前后依赖关系,所以使用CNN能获得一定的特征表达,那么在CTR任务中使用CNN能获得特征提取的功能吗?
答案是能,但是效果可能没有那么好,问题就出在卷积是对连续的width
个特征进行计算,这导致了我们输入特征的顺序发生变化就会引起结果的变化,而在CTR任务中,我们的特征输入是没有顺序的。
这相当于我们给了一个先验在里面,就是连续的width
个特征进行组合更具有意义。
虽然我们可以使用类似空洞卷积的思想增加感受野来使得卷积计算的时候跨越多个特征,但是这仍然具有一定的随机性。
所以使用CNN进行CTR任务的特征提取的一个难点就在于其计算的是局部特征组合,无法有效捕捉全局组合特征。
- Flexible pooliong是什么?
其实就是Max Pooling,只不过每次沿某一维度取p个最大的,不是1个最大的。
p的取值根据当前池化层数和总层数自适应计算,其中i
是当前层数,l
是总层数
核心代码
这里就简单贴一下卷积池化还有最后全连接层的对应代码,完整的代码请参考CCPM。
for i in range(1, l + 1):
filters = conv_filters[i - 1]
width = conv_kernel_width[i - 1]
k = max(1, int((1 - pow(i / l, l - i)) * n)) if i < l else 3
conv_result = tf.keras.layers.Conv2D(filters=filters, kernel_size=(width, 1), strides=(1, 1), padding='same',
activation='tanh', use_bias=True, )(pooling_result)
pooling_result = KMaxPooling(
k=min(k, conv_result.shape[1].value), axis=1)(conv_result)
flatten_result = tf.keras.layers.Flatten()(pooling_result)
final_logit = MLP(hidden_size, l2_reg=l2_reg_deep,
keep_prob=keep_prob)(flatten_result)
Feature Generation by Convolutional Neural Network for Click-Through Rate Prediction
文章的主要贡献点有2个:
- 使用重组层进行特征生成缓解了CCPM中CNN无法有效捕获全局组合特征的问题
- FGCNN作为一种特征生成方法,可以和任意模型进行组合
模型结构
-
分组嵌入
由于原始特征既要作为后续模型的输入,又要作为FGCNN模块的输入,所以原始特征的embedding向量可能会遇到梯度耦合的问题。
这里对于FGCNN模块使用一套独立的embedding向量,避免梯度耦合的问题。