FNN 网络介绍与源码浅析

FNN 网络介绍与源码浅析

前言

周五晚上分享 paper !!! 感动自己一把~ 😂 感觉本周看的 Paper 还挺多的, 打算尽可能都做下记录, 方便日后查阅.

广而告之

可以在微信中搜索 “珍妮的算法之路” 或者 “world4458” 关注我的微信公众号;另外可以看看知乎专栏 PoorMemory-机器学习, 以后文章也会发在知乎专栏中;

文章信息

核心观点

本文主要介绍了两个网络 FNN (FM supported NN) 以及 SNN (sampling-based NN), 我重点看了下 FNN 而不关心 SNN. FNN 的核心是在设计 Embedding Layer 时, 使用的参数量和 FM 一致, 这样的话, 可以通过预训练 FM, 然后使用 FM 的参数来初始化 Embedding Layer. 由于存在预训练的过程,
所以降低了整个网络的训练过程中的开销, 模型可以更快的收敛. 在 xDeepFM 论文中有提到 FNN 的不足: FNN (PNN 亦如此) 只关注于高阶的特征交叉, 而忽视了低阶的交叉特征. (Wide & DeepDeepFM 通过引入线性层(shallow component), 和 DNN (deep component) 结合来解决低阶交叉特征被忽视的问题.)

核心观点介绍

FNN 的网络结构图如下:

可以发现, 主要还是经典的 Embedding + MLP 结构. 其核心在于设计 Embedding Layer 时, 按照 FM 的思路来设置. 回忆 FM 的公式是:

y F M ( x ) : = sigmoid ⁡ ( w 0 + ∑ i = 1 N w i x i + ∑ i = 1 N ∑ j = i + 1 N ⟨ v i , v j ⟩ x i x j ) y_{\mathrm{FM}}(\boldsymbol{x}):=\operatorname{sigmoid}\left(w_{0}+\sum_{i=1}^{N} w_{i} x_{i}+\sum_{i=1}^{N} \sum_{j=i+1}^{N}\left\langle\boldsymbol{v}_{i}, \boldsymbol{v}_{j}\right\rangle x_{i} x_{j}\right) yFM(x):=sigmoid(w0+i=1Nwixi+i=1Nj=i+1Nvi,vjxixj)

那么 FNN 在设计 Embedding 时, 设置每个 Field 对应的 Embedding 权重为 W i ∈ R ( K + 1 ) × ( e n d i − s t a r t i + 1 ) \bm{W}^i\in\mathbb{R}^{(K + 1)\times (\mathrm{end}_i - \mathrm{start}_i + 1)} WiR(K+1)×(endistarti+1), 其中 s t a r t i \mathrm{start}_i starti e n d i \mathrm{end}_i endi 是第 i i i 个 Field 下的特征的起始和结束索引值. 注意到每个特征的 emb z i \bm{z}_i zi 大小为 K + 1 K + 1 K+1, 它表示为:

z i = W i ⋅ x [ start ⁡ i : end ⁡ i ] = ( w i , v i 1 , v i 2 , … , v i K ) \boldsymbol{z}_{i}=\boldsymbol{W}^{i} \cdot \boldsymbol{x}\left[\operatorname{start}_{i}: \operatorname{end}_{i}\right]=\left(w_{i}, v_{i}^{1}, v_{i}^{2}, \ldots, v_{i}^{K}\right) zi=Wix[starti:endi]=(wi,vi1,vi2,,viK)

它可以看成由两部分组成, 其中 w i w_{i} wi 正好和 FM 中的一阶特征对应的权重对应起来, 而 ( v i 1 , v i 2 , … , v i K ) \left(v_{i}^{1}, v_{i}^{2}, \ldots, v_{i}^{K}\right) (vi1,vi2,,viK) 和 FM 中每个特征对应的隐向量对应起来了. 这样的话. 另外注意到网络结构图中还有一个 w 0 w_0 w0, 可以认为是偏置. 这样的, Embedding Layer 中的权重和 FM 中的权重参数一致, 因此可以使用预训练的 FM 中的权重来初始化网络的 Embedding Layer.

https://github.com/Atomu2014/product-nets/blob/master/python/models.py 中实现了 FNN: (这个代码是 PNN 的作者实现的, 有的细节可以查看 Product-based Neural Network (PNN) 介绍与源码浅析, 哈哈, 随时随地打广告 😂 😂 😂, 原作者的代码基于 Theano 实现, 不太想看~~)

核心代码如下, 非常简单:

## num_inputs 是 Field 的个数
for i in range(num_inputs):
    init_vars.append(('embed_%d' % i, [field_sizes[i], embed_size], 'xavier', dtype))
node_in = num_inputs * embed_size
for i in range(len(layer_sizes)):
    init_vars.append(('w%d' % i, [node_in, layer_sizes[i]], 'xavier', dtype))
    init_vars.append(('b%d' % i, [layer_sizes[i]], 'zero', dtype))
    node_in = layer_sizes[i]

## xw 就是 W * x, 得到每个特征对应的 Embedding, 然后 Concat 起来
## 最后输入到 MLP 中
w0 = [self.vars['embed_%d' % i] for i in range(num_inputs)]
xw = tf.concat([tf.sparse_tensor_dense_matmul(self.X[i], w0[i]) for i in range(num_inputs)], 1)
l = xw

for i in range(len(layer_sizes)):
    wi = self.vars['w%d' % i]
    bi = self.vars['b%d' % i]
    print(l.shape, wi.shape, bi.shape)
    l = tf.nn.dropout(
        utils.activate(
            tf.matmul(l, wi) + bi,
            layer_acts[i]),
        self.layer_keeps[i])

l = tf.squeeze(l)
self.y_prob = tf.sigmoid(l)

结论

夜里 12:06, 收摊喽~~ 😂

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值