Paper-Touching

2018 - 2019

Attention Is All Your Need

关于Attention的定义

Attention函数可以看做是一个映射,从 query && key-value对的集合 -> output 的映射 。其中 query, key, value, output 均是向量。

由 key & key 算出一个归一化的常量,然后用这个常量在对应的value上加权;加权后的结果相加,就是output .

两种常见的attention

一种是 additive attention (Dzmitry Bahdanau, Kyunghyun Cho, and Yoshua Bengio. Neural machine translation by jointly learning to align and translate. CoRR, abs/1409.0473, 2014.), 另一种是 dot-product(multiplicative) attention.

尽管加法attention和点积attention有理论上相同的复杂度,但是点积attention在实际中更快,更省内存;因为它可以用矩阵乘法来高度优化!

当query和key的维度比较小时,加法attention与点积attention效果类似;但是当其维度较大时,加法attention就比不带scale的点积attention好! 猜测是因为当维度大时,点积结果的magnitude很大,从而进入到softmax函数的极度低梯度的范围。 所以,为了抵消这个影响,我们用 $ sqrt d_k $ 来缩放这个magnitude.

为什么magnitude会很大? 是因为 query, key 都是均值为0,方差为1的独立随机变量,它们的点积 $ q dot k = sum_{i=1}^{d_k} q_i k_i $ 就是一个均值为0,方差为 的 $ d_k $ 的结果。

这也解释了为什么要除以 $ sqrt d_k $: 这样方差又成了1 ??

Multi-Head Attention

传统的attention,就是在 query, key, value 上直接算一个加权结果。Multi-Head attention, 则是将用多个映射,分别将 query, key, value 单独映射为多个表示 [ (query_1, key_1, value_1), (query_2, key_2, value_2), ...],再在映射的结果上分别算attention,得到 [output1, output2, ...], 最后把这些output拼接后做一个映射,得到最终的output;

好处就是,允许模型联合地去关注输入的不同位置的不同子空间的表示。这个是单个的attention所不能做到的。

其实还是好理解,就类比与 CNN 的多个filter吧。

实际种,用的一个矩阵来分别映射query,key,value; 而且,映射后的维度为原始维度除以head的数量,这样其实整体的运算量不变。

Get-to-the-point: Summarization with pointer-generator networks

Attr

author
See Abigail

Google Brain & stanford NLP

Run code

repo: https://github.com/abisee/pointer-generator

  1. download data

作者给出了完整的数据处理流程,放在 https://github.com/abisee/cnn-dailymail 下。

不过我们使用一个用户(见讨论 https://github.com/abisee/cnn-dailymail/issues/9 )提供的已经处理完的数据,结果在 https://github.com/JafferWilson/Process-Data-of-CNN-DailyMail

下载其中的 FINISHED_FILES 对应的链接里的文件,得到一个zip,解压后是如下的结构:

chunked/
    test_000.bin
    ...
    test_011.bin
    train_000.bin
    ...
    train_287.bin
    val_000.bin
    ...
    val_013.bin
test.bin
train.bin
val.bin
vocab

其中 chunked 存储的是将外边对应的文件按照1K每份做划分后的结果——划分是为了后面训练时多进程读取输入。

*.bin 是使用 abisee/cnn-dailymail 仓库中的 make_datafiles.py 脚本处理原生txt的结果。 处理过程大概是用 tensorflow.core.example.example_pb2.Example 对象来存储tokenize过的article和abstract, 然后序列化这个对象, 并以二进制方式写入到文件。则应该是tf标准的处理方式。暂时先不管。

  1. 安装tf

还是觉得在公司电脑上运行,所以登上去用virtualenv 装了tf1.2;但是看README是1.2.1,不知道有没有差别;

此外,需要重新把文件下载到服务器上。好麻烦……

  1. 运行

搞定。用tf1.2顺利把train跑起来了。还通过tensorbord看了下loss(scalar);不过看graph和embedding都失败了。 应该是没有把graph保存下来;embedding查看则一直在parsing,不知道是不是工作用的Mac air性能太差了。

不管怎么说,前期运行已经OK了。下面就是看代码了!

Reading Code
主入口是 run_summarization.py
part1: config-argument definitions
part2: global function
    a. calc_running_avg_loss
        平滑loss;每一步将之前的累积loss decay,同时加上缩放过的当前一步的loss,得到新的累计loss
        以此新的累计loss为当前的loss
    b. restore_best_model
        将eval的模型拷贝到train下;其中用到了tf的参数恢复的能力!
    c. convert_to_coverage_model
        转换模型
    d. setup_training
        设置training & 跑training; 使用了tf.train.Supervisor
    e. run_training
    f. run_eval
    g. main
        判定是解码时,设置 batch-size = beam-size. 利用是
        in decode mode, we decode one example at a time. On each step, we have
        beam_size-many hypotheses in the beam,
        so we need to make a batch of these hypotheses.
        应该得结合beam-search怎么做的来看了。

        用一个namedtuple来存储flags的解析的且需要的东西

        用 tf.set_random_seed 来设置随机数种子

        在decode模式下可以看到:将 max_dec_steps 强制设为1了;解释说是每次做一步!然后调用的是
        BeamSearchDecoder.decode 来做的。
接下来看下 model.py

这个应该是我们核心要学习的。

SummarizationModel

    _add_placeholders
        输入部分
        enc_batch, int32, (batch-size, None), 说明每次每个batch的size部署固定的!
        enc_len, int32, (batch-size), batch中每个句子的长度?
        enc_padding_mask, float32, (batch-size, None) mask 处理!
        如果是 pointer-gen 网络
            enc_batch_extend_vocab, int32, (batch-size, None) 每个instance的扩展vocab
            max_art_oovs, int32, [], 不清楚是什么

        dec_batch, int32, (batch-size, None)
        target_batch, int32, (batch-size, None)
        dec_padding_mask, float32, (batch-size, None)

        decode & coverage时
            prev_coverage, float32, (batch-size, None)

    _add_encoder
        创建lstm cell,用的是
            tf.contrib.rnn.LSTMCell
        这个和 tf.nn.rnn_cell.LSTMCell 是等价的(alais); initializer 用的是同一个initializer:
            self.rand_unif_init = tf.random_uniform_initializer(
                - rand_unif_init_mag, rand_unif_init_mag, seed=123
            )
            state_is_tuple = True, 默认行为;返回的结果有

        创建双向LSTM网络,用的是
            tf.nn.bidirectional_dynamic_rnn
        传入了 sequence_len,这个应该是来自data部分的输入;
        swap_memory = True, 这个参数的解释是
        Transparently swap the tensors produced in forward inference but needed for back prop
        from GPU to CPU. This allows training RNNs which would typically
        not fit on a single GPU, with very minimal (or no) performance penalty.
        似乎是多GPU时把这个参数打开;默认是False的;
data.py 模块处理数据

比较有意思的:

在从外部字典文件加载到内部字典时,会把最后一个加入的词打出来——方便定位,很细心。

如下是特殊字符:

# <s> and </s> are used in the data files to segment the abstracts into sentences.
# They don't receive vocab ids.
SENTENCE_START = '<s>'
SENTENCE_END = '</s>'

PAD_TOKEN = '[PAD]' # This has a vocab id, which is used to pad the encoder input, decoder input and target sequence
UNKNOWN_TOKEN = '[UNK]' # This has a vocab id, which is used to represent out-of-vocabulary words
START_DECODING = '[START]' # This has a vocab id, which is used at the start of every decoder input sequence
STOP_DECODING = '[STOP]' # This has a vocab id, which is used at the end of untruncated target sequences

包含一个用于TensorBoard可视化的函数。

有一个函数来生成 tf.Example , 其中用 glob.glob 函数来扩展通配符,这个挺不错的。从data中读取tf.Example 时,用了 struct 这个标准库,这个是用来以二进制方式在C类型与Python类型做交换的;不是特别懂这个,可能算是序列化的 一种方式?用 struct.unpack 来完成的。

原来,虽然在generator机制下,input中的UNK(不出现在全局词典中)会被拿出来作为额外的字典; 但是训练语料中abstract的内容中,可能仍然含有不在全局词典 + input额外词典中的词,所以 训练语料的输入中,还是有可能有UNK!

Hierarchical Attention Networks for Document Classification

Influence

层次化建模文档的一个重要工作。引用数截止到2018年10月31日已经超过了500.

常看到 HAN 结构,就是这篇论文里提到的模型,也就是 Hierarchical Attention Networks.

Motivation

目前流行的神经网络没有考虑文档的结构信息,这篇文章试图验证猜想(直觉):在模型里上加入文档结构的知识,能够帮助我们获得更好的表示。

we test the hypothesis that better representations can be obtained by incorporating knowledge of document structure in the model architecture.

隐含在这个直觉之后的,是作者认为在回答一个问题时,文档中各部分不是相同程度地相关的;度量这种相关性,需要建模词之间的交互,而不仅仅是看其是否孤立地存在。 (这个好像跟 text-classification 没有关系??)

Contributions

论文的introduction提到,主要贡献就是新的神经网络结构: HAN.

具体来说

(1)模型有一个层次化的结构,来刻画文档的层次化结构,更符合直觉。

(2)基于层次化结构,在词级别和句子级别,都使用了Attention机制。使得模型在两个层次上有能力捕捉到对文档建模真正有用的信息。

A Neural Attention Model for Sentence Abstractive Summarization

Authors

Alexander M.Rush, (现在哈佛任助理教授,主要做 data-driven的工作,把DL与structure-prediction 结合) Corpra Sumit, Weston Jason

整个工作是facebook的。

个人评价

开坑之作。现在来看觉得训练数据很有问题:为啥用1st sentence作为输入就可以生成headline呢? 这点站不住脚。

构建训练集

核心方法: 对Gigaword (Graff et al., 2003; Napoles et al., 2012), 将 headline 与 文章第一句 作为输入,即

(first-sentence-of-article, headline)

得到 9.5 百万的输入;

启发式过滤:因为Gigaword contains mainly spurious headline-article pairs, 所以启发式地对以下情况做过滤:

  1. 如果除去停用词就没有词了 (no non-stop-words)

  2. 标题有 作者信息(byline) 或者 无关的编辑标记 (extraneous editing marks)

  3. 有问题标题或者冒号

过滤后只有 4 万的输入;

基础预处理

  1. PTB tokenization

  2. lower-casing

  3. replace all digit with #

  4. replace word-type seen less than 5 times with UNK

词表统计

输入(first-sentence-of-article): 119million tokens, 110K unique word-types (average 31.3 words per. sent) 摘要/标题(headline): 31 million tokens, 69K unique word-types (average 8.3 words per. headline)

额外过滤

因为模型训练出来要在DUC-2004上做evalution,所以去掉了 DUC-2004 时间区间的文章。 (没说影响的文章数有多少)

2020

BART: Denosing Sequence-to-Sequence Pre-training for Natural Language Generation, Translation, and Comprehension

优势

在判别式任务上与RoBERTa效果相似,但在生成任务上效果更好。

model

是一个 seq2seq结构(也就是Transformer),base设置下encoder/decoder 各6层; large设置下 encoder/decoer 各12层。

因为比BERT多了decoder对encoder的互动,整体比同规模BERT多10%的参数。

预训练模式

方式:先corrupt数据,让模型尝试复原。优化这个reconstruction-loss.

BART允许任意的document corruption.

corrpution的方式有多种,分别是: token mask, token deletion, token infilling(span tokens replace with 1 mask), sentence permutation, document rotation.

Finetuning 方式

分类任务: encoder, decoder都输入相同的内容,其中输入内容的最后一个token为”end”, 用这个token的decoder的final hidden state表示送给一个新的linear classifier.

Token分类任务:如SQuard, 同样用decoder的 final hidden state.

序列生成任务: BART有autoregressive的decoder,可以直接finetune.

探索使用BART来提升机器翻译的decoder

前人有工作说明机器翻译可以通过预训练的encoder来提升效果,但是预训练的decoder作用不大。 这里尝试用整个BART来提升效果,主要是提升其他语言翻译为英语的效果。

核心思路就是把BART encoder中的embedding层给换掉,换成适配其他语言的embedding, 使用随机初始化。

训练分为两个步骤: 第一步 先固定住BART的大部分参数,然后主要训练embedding层, position,第一层self-attention的projection。 第二步,用比较小的迭代轮次更新整个参数。

与其他训练目标比较

因为发布的模型在训练数据、训练资源、模型结构、finetuning过程不同,因此 作者重新实现了很多的训练目标。用BERT来作为参照,因为BERT的设置和这里是一致的: 1M步,使用book (corpus)和 wikipedia数据。

与其他模型的区别

GPT只建模了左边的context,对某些任务是有问题的; ELMO分别建模了从左到右和从右到左, 但是彼此缺乏交互。

BERT不是auto-regressive,生成任务效果打了折扣。

unilm的预测是 条件独立的; BART避免了训练和预测的不同,因为BART的decode的输入永远是 没有corrupt的数据。

MASS比较像BART,它把输入侧的连续token mask掉,在decoder侧预测。 它在判别型任务上效果不好,因为encode和decoder的输入token集合是不想交的。

Billion-scale Commodity Embedding for E-commerce Recommendation in Alibaba

作者: jizhe Wang, Pipei Huang(黄丕培). (见 万物皆向量——双十一淘宝首页个性化推荐背后的秘密

大名鼎鼎的 EGES. 淘宝主要面临3个挑战: scalability, sparsity, cold-start. 这篇文章就要解决这3个问题。

文章亮点

  1. 介绍了一种 GE 方法,可以大规模应用,对 GE 以及推荐系统 中常见的 稀疏、冷启 问题都有一定解决

  2. 介绍了 Taobao 线上实际的部署方法,值得一看

1. 概述

GMV: Gross Merchandise Volume (总成交额)

Double-Eleven Day: 双11

Taobao:

是 C2C 平台;淘宝有 10 亿用户, 20 亿 items (commodities). 贡献阿里 75% 的流量;

最主要的问题,让用户快速找到需要的、感兴趣的商品! 推荐是其中的关键技术。 手机淘宝主页基于用户历史行为生成,占据推荐流量的40%; 推荐贡献了最要的营收(revenue)和流量。

Scalability: 在 10 亿用户 20 亿物品前,很多推荐方法不好使;

Sparsity: 用户只与部分 item 有行为。

Cold-Start: 每小时,有百万级别的新 item 被上传到系统;这些 item 没有用户行为;处理这些物料,或者将这些物料推荐给 用户,是一个困难的事情。

使用 matcing -> ranking 二阶段策略; matching 是给用户有行为的 item,生成1个相似 item 候选; ranking 基于用户的偏好,用 DNN 排序候选 commodities. 每阶段面对不同的问题,有不同的技术解决方式。

这篇文章主要关注 matching 阶段!

CF 的方法,主要考虑用户历史中,物品间的 co-occurence. 这里用 item 图上的 random-walk, 可以 items 间的高阶相似; 这被称为 BGE (Base Graph Embedding).

BGE 比 CF 强,但是依然解决不了只有很少行为甚至没有行为的 item;为了解决这个问题,因而提出了利用 side-information 提升 Emb 生成的方式,即 GES (Graph Embedding with Side information)。

又,淘宝的商品有很多种类型的 side information, 例如 类别、品牌、价格等; 经验性地,不同类型的 side information 对 commodities emb 贡献不同,因此有必要在 side information 上考虑加权; 这种模型被称为 EGES (Enhanced Graph Embedding with Side information)

总结,在 matching 阶段,有 3 个重点工作:

  1. 基于用户行为,构建 item graph

  2. 学习 item embedding (EGES, GES 优于 BGE)

  3. 部署 graph embedding system. (在自研的 Xensorflow 上)

2. 方法

2.1 构建 item graph

图是 加权有向 图;

  1. 将用户连续的行为,拆分为 session-based behaviour.

    将连续的用户行为,按 1 个小时为 window 拆分为多个 session.

    Why: a. 如果不拆分,序列太长,计算、存储开销大 b. 用户的兴趣随时间有漂移

    其实这里觉得细节还不是太清楚——

    拆分为多个 session,应该是每个 session 都会用吧?而不是只用最近1个小时的? - 如果是每个 session 都用,那这个相比用整个行为序列,也不能减少多少计算、存储开销? - 但只有那个最后1个 session,想想还是不太可能…… - 应该是用全不的 session; - 切分为 session,相比不切,按照后面的构建边的方式,其实就是少了跨 session 的边; 这种量,可能积累起来还是比较多的吧——毕竟会有很多个 1 个小时切分;

    拆分的起始时间是统一的,还是基于每个用户的行为序列的起始时间?或者是结束时间(当前时间倒推)? - 应该是基于每个行为序列的起始时间?相比倒推,这样能够保证每次计算都是一致的结果; - 其实时间统一,不太现实,也没必要?

  2. 基于 session-based behaviour, 在 图中连有向边。 如 序列是 A D B. 则连边 A -> D; D -> B;

  3. 计算每条边的权重: 就是这条边被连了多少次。

    这样,图上的每条边,其实是全部用户行为的表现。

需要过滤掉一些噪声数据:

  1. stay after click less than 1s

  2. spam user (3 个月内买 1,000 个 item,或者点了超过 3,500 的用户)

  3. item 的 id 没变,但是零售商把其内容大幅改变了

2.2 计算 emb
2.2.1 方法1: BGE

就是利用 DeepWalk 方式来构建 Emb;

具体地:

  1. 随机游走,得到 item 序列 数据集

    随机游走方式:论文里没有详细描述,只说了

    从1个节点到另一个节点的概率:

    \[ \begin{align}\begin{aligned}\begin{split}p(v_j | v_i)) = \begin{cases} \frac {M_{i, j}} {\sum_{j\in N_+{(v_i)}} M_{i,j}}, & v_j \in N_+(v_i) \\ 0, & e_{ij} \notin E \end{cases}\end{split}\\很简单,就是有边的就按归一化权重走;没边的不走;\end{aligned}\end{align} \]

    但是 1. 如何选起始节点 2. 路径长度 3. 总共生成多少个

    没有细说 => 在后面的实验中,有提到。

  2. 得到 item 的序列 数据集后,直接用 word2vec 的 Skip-Gram + negative-sampling (图里面画的是 smapled softmax, 可能差别没有那么大)模式训练即可。

2.2.2 方式2: GES

BGE 没法处理冷启动问题;需要考虑 side information.

编码也非常简单——每个 side-information 和 item id 一样的等同对待,one-hot => 映射为 d 维的向量 => avg pooling, 就得到了 item 的表示向量。

训练方式依然保持不变。

2.2.3 EGES

BGE 只是简单的把各个 side-information 平均起来,一个简单的优化就是加权求和。

权重怎么定义? 有如下候选可以考量:

  1. 是 1 个 side-information 定义1个固定权重? 这样显然表现能力有限

  2. 是每个物品的每个 side-information 都对应 1 个权重? 这样显然很稀疏

  3. 还是用 attention 思想,定义1个 weight 向量,通过与各个 side-information 向量交互得到权重?看起来不错。

然而,论文用的方法2…… 论文里说,申请了一个 A matrix, shape是 \(|V| \times (n +1)\), 其中 n 就是 side-information 个数,+ 1 是因为还有 item-id 的这个域;|V| 就是图里 vertex 个数,也就是 item 的个数了。

不用 attention 的方式来做,我觉得是不太好的…… 说白了,这里没有用矩阵分解(即 attention)来算权重, 而是独立的标量,对泛化可能会有很大的影响 —— 且不说过拟合,就是你后面对冷启动物品,怎么得到side-information的权重呢?

从后文来看,对冷启动物品,是直接取的 average, 不说简单粗暴,至少也是退化到 GES 了,与 EGES 框架就不搭了。

考虑到 2017 年, NLP 里的 attention 早就用烂了,这里没有任何说明,还是值得 argue 的。

\(rightarrow\) 事实上,在文章最后的 Future Work 里,利用 Attention 就是未来的工作……

加权求和,需要对权重先做归一化(和为1)。论文里权重归一化用的是 softmax \(e^{a_{v}^{j}}\) ; 论文里说这是为了保证每个 side-information 权重都大于0(的确!)

> 论文没有点明用的是 softmax 归一化, 但是从公式来看确实是。

3. 实验

用于验证效果的方法:

  1. link prediction task (offline Evaluation)

  2. online experimental result on Mobile Taobao App.

  3. some real-world cases

3.2 在线 A/BTest

方法

基于 Item 的 Embedding, 计算每个 item 的 相似item, 输入到排序模型,作为 Taobao Mobile 主页推荐的结果。

相似结果的好坏,直接影响到推荐结果!

没有说每个 item 要生成多少个相似 item,也没有说这套系统在实验过程中,Emb 是不是根据行为、新上传 item 实时更新的。 我觉得这两点应该挺重要的。

对比方法

Method

Remark

Base

Item-CF 的方法,考虑了物品的(在行为中的)共现,以及用户的voting weight. 这套方法在 GE 应用前在淘宝大规模应用,用了很多人工启发式的规则(主要用来计算 user voting weight?)。

BGE

GES

EGES

各个方法出来结果后,用的是一套 rank .

实验设置

使用 CTR 作为指标。

实验做了 7 天,做实验的时间是 2017 年 11 月。

效果

Base 好于 BGE; EGES > GES > Base;

3.3 Case Study

研究的是 EGES 的向量表现。

3.3.1 向量可视化

把鞋子的 Embedding,用 projector-tensorflow 来可视化(PCA 方式)。

可以看到,不同 category 的鞋子,分属于不同的聚类(说明 category 对应的向量,在加权后的整体向量里还是挺有影响力的);

进一步的,发现 badminton 和 table tennis 聚类很接近,与 football 较远。作者分析说,这表示中国人里, 喜欢 羽毛球 和 乒乓球 的人有较大的重叠;而喜欢足球的人,与喜欢羽毛球、乒乓球这些室内运动的人重叠很少。

> 挺有意思的!

3.3.2 冷启动物品效果

如果构建 冷启动物品 向量?

非常简单,把冷启动物品的各 side-information 对应的 emb, 平均一下,就是冷启动物品的向量表示了。

效果

论文里看了 2 个case的效果:分别选了属于衣服和毛巾的一个商品,查看 Top4 相似的商品。看起来效果还是很好的,如论文截图:

_images/02_eges_figure_5_sim_items_for_cold_start.jpg

基于该图中找到的相似 item 与冷启动 item 具有的相似属性, shop 这个 SI 的影响比较大。论文说这是因为 item 的 SI 中,shop 的权重 比较高(下一节会分析),对 item 的最终表示影响较大,因而在 冷启动物品 找相似的过程中,shop 的影响也较大 (因为冷启物品的表示是各个 SI 的平均,而其他训练过的 item shop 的 SI 权重高,那自然在向量匹配时, shop 的影响就大了)。

3.3.3 EGES 中各 SI 权重

作者从 8 个 category 中各找了 1 种物品,可视化了 SI 的权重分布,如下图:

_images/02_eges_figure_6_weight_vis.jpg

作者据此图给出了 3 点观察和分析:

  1. 各个物品的 SI 权重分布都是不同的,这印证了论文的假设: 不同物品的 SI 贡献不同。

  2. item-id 在各个物品中的权重都是最高的,这说明:item-id 对应的 item 本身才是用户行为的关键,而 SI 只是辅助。 —— 不过,离开了这个辅助,也就是 BGE, 效果就没有那么好了。

  3. 所有物品中, SI shop 是除 item-id 外权重最高的,这与用户的行为相一致: 用户倾向于买同店铺的东西,因为方便和便宜(满减优惠?)

    分析还是很好的。

4. 系统部署与操作

整体框图

_images/02_eges_figure_8_system_overview.jpg
TPP

Taobao Personality Platform.

RSP

Ranking Service Platform.

XTF

基于Porsche blink的分布式Tensorflow训练及在线打分平台 (来自 一天造出10亿个淘宝首页,阿里工程师如何实现?)

从现在的视角来看,比较常规的图:分为 在线、离线 两个部分。在线部分处理实时请求,离线部分计算、更新向量。

在线部分

从用户进入 Taobao Mobile App 开始,TPP 拉取用户最新的信息(应该就是行为历史),从 offline-subsystem 中获取候选 items; 然后交给 RSP 排序(基于 DNN 的),最后返回给用户。

这里需要关注的点,就是拉取相似 item 的计算,从图中来看,应该就是读的缓存(例如 Redis)。 不确定实际中或者现在是否是实时计算的。

离线部分

这里就是体现 EGES 实际上线部署的工作了。

  1. 处理用户行为日志: 一般拉近 3 个月的,然后左 anti-spam 处理,剩余的大概有 600 billion 的 entries.

  2. 构建图和随机游走序列: 因为数据太多,因此实际中,不是放大 1 个图里, 而是利用 Open Data Processing Service (ODPS) 并行处理拆分后的子图。 子图大概 50 million 的 nodes. (即 5 千万的物品)。 每个子图上,基于 ODPS 的 iteration-based distributed graph framework 来生成随机游走序列。

    所有序列生成后,共有大约 150 billion 的序列。

  3. 训练 emb: 基于 XTF,用 100 块 GPU 训练。

整体上,共有 获取日志 \(\rightarrow\) anti-spam处理 \(\rightarrow\) item-graph构建 \(\rightarrow\) 随机游走-序列生成 \(\rightarrow\) 训练embedding \(\rightarrow\) item2item 相似计算 \(\rightarrow\) 生成 I2I map 这些步骤,作者说可以在少于 6 小时的时间内全部完成。

这大概就是算法和强大工程结合的魅力。 有一些小疑惑:

  1. 是否每隔一段时间(例如这里是 6 小时),就全量算一遍?

  2. 冷启 item 生成 emb ,是另一个独立的过程在做? 还是说只在全量更新里完成。

5. 相关工作

5.1 Graph-Embedding

GE 是一种通用的 网络表示(Network Representation) 的方法!

可以分为 3 类工作,

  1. 因子分解方法

    LINE 是其中的代表。

  2. 深度学习的方法

    Deep neural networks for learning graph representations, AAAI 2016

    Transnet: Translation-based network representation learning for social relation extraction. IJCAI 2017

    Structural deep network embedding. KDD 2016

  3. 随机游走的方法

    metapath2vec: Scalable representation learning for heterogeneous networks. KDD 2017

    Node2vec: Scalable feature learning for networks. KDD2016

    Deepwalk: Online learning of social representations. KDD 2014

5.2 Graph-Embedding with side-information

GE 只利用了图的拓扑结构信息,存在 稀疏、冷启动 问题。利用 side-information 是一种今年来尝试提升 GE 表示的方式。

主要的出发点是,如果一些节点有相同的 side-information, 那么他们应该在向量空间中相近。

一些工作:

  1. 多任务学习:联合 embedding 任务和分类任务

    Discriminative deep random walk for network classification. ACL 2016

    Max-margin deepwalk: Discriminative learning of network representation. IJCAI 2016

  2. 使用知识图谱、文本、图片信息

    Representation learning of knowledge graphs with hierarchical types. IJCAI 2016

    Cane: Context-aware network embedding for relation modeling. ACL 2017

    Text-enhanced representation learning for knowledge graph. IJCAI 2016

    Network representation learning with rich text information. IJCAI 2015

    Incorporating knowledge graph embeddings into topic modeling. AAAI 2017

    Heterogeneous network embedding via deep architectures. KDD 2015

5.3 Graph-Embedding for Recommendation System

推荐系统已经成为 GE 最流行的下游任务之一。

一些工作:

Personalized entity recommendation: A heterogeneous information network approach. WSDM 2014

Collaborative knowledge base embedding for recommender systems. KDD 2016

Meta-graph based recommendation fusion over heterogeneous information networks. KDD 2017

Scalable graph embedding for asymmetric proximity. AAAI 2017

6. Future Work

2 个方向:

  1. 利用 attention 机制,更好的加权不同的 SI

  2. 将 文本信息 加入到网络, 更好地利用大量用户的评论。

Deep Neural Networks for YouTube Recommendations

Paul Covinton, Jay Adams, Emre Sargin, Google, Mountain View, CA

经典论文。2016年的文章了。

相关博客文章

  1. DNN YouTube Recommendations 召回

    该文章仅关注召回部分。

    softmax 参数直接用item 的向量

    在softmax阶段均采用图二中构造用户历史embedding序列时的与商品id对应embedding商品矩阵(即YouTubeNet中的视频矩阵)做内积计算。

    SESSION-BASED RECOMMENDATIONS WITH RECURRENT NEURAL NETWORKS

    (负)采样方法

    不是从列表页中,选择没有点击过的,而是:

    从当天所有点击过的商品中,除去当前用户点击过的商品,从剩余商品中随机选择 20 个商品作为负样本。

YouTube推荐时主要有3个挑战:

  1. scale 大规模;高分布式学习与高效部署

  2. Freshness 实时性;2个方面,一方面每秒都有大量新视频传上来;另一方面要尽快基于用户的近期action更新用户画像;

  3. Noise 噪声,用户行为中有大量噪声

Google内部开始将基本上所有的learning-problem的通用解决范式,都迁移到深度学习模型。 该论文的模型也是如此。其有10亿参数,1000亿训练样本。

2. SYSTEM OVERVIEW 系统概览

主要有2个网络,第一个网络用于候选生成,百万级别到百级别;第二个网络用于排序。

候选生成网络,输入是用户的历史行为,输出是几百个与用户相关的物料。论文里说 The candidate generation network only provides broad personalization via collaborative filtering , 这是说这个网络做的事情跟协同过滤本质相同? 另外,最后一句 The similarity between users is expressed in terms of coarse features such as IDs of video watches, search query tokens and demographics. , 表面是说用户相关性的表达通过这些粗糙的特征(观看的视频id序列,搜索query token,人口信息), 实际就是说这个网络中用户的实际特征是这些?

排序网络,用的特征更细细粒度,fine-level. 用了更多用户、视频的特征。做法是给每个视频打一个分,取top \(\rightarrow\) 也就是点估计。

3.1 推荐作为分类

推荐本来是做筛选,可以转化为打分——对每个item打分,然后取TOP;论文里说将其作为分类 softmax , 其实也类似:毕竟 softmax 输出一个概率,也可以作为分数。

用户U,在上下文C下,是否要看视频 \(w_i\),用softmax

4.1 特征表示

Embedding Categorical Features 类别向量特征

Video-ID 这种词典特别大的,按点击频次排序取 TOP-N;

OOV 直接用 0向量 (没有用 UNK );

候选生成网络, 多个值得情况(如历史观看 videos ),直接取平均然后输入到网络;

不同特征域用到同一类特征,底层共享 emb: 比如 video-id 在 “曝光”,“最后一个观看 video”,“video ID that seeded the recommendation”,这里面用到的 video-id 对应的 emb, 底层都是1个 emb : 好处是泛化,减少网络对内存的消耗

Unified Language Model Pre-training for Natural Language Understanding And Generation

预训练设置

  1. 一个batch里,Bidirectional LM, Unidirectional LM, Seq2Seq LM 的目标各占 1 / 3.

  2. 模型结构和BERT-large相同,与GPT一样,使用gelu激活函数;24-layer, 1024 hidden size, 16 attention heads, 大约340M参数。

    基于 BERT-large 初始化

  3. 数据上,使用English Wikipedia 和 BookCorpus. (跟BERT一样)

  4. 输入序列最大长度是512 (看起来后面的finetune阶段更长一些,为788!)

  1. mask策略上,15%的概率做mask:

    做mask的时候,80%概率mask token为 [MASK] , 10%随机替换,10%保持不变; 替换为mask时,80%替换unigram,20 bigram或trigram.

  2. Adam, beta1 = 0.9, beta2 = 0.99; lr = 3e-5;

    linear warm-up at first 4W steps, linear decay; dropout-rate = 0.1; weight-decay = 0.01! batch-size = 330; total steps = 77W steps, 7hours/1W steps, 所以一共要 77 * 7 = 539 h = 22 days; 8张 V100 32G, 混合精度训练

疑问:

  1. BERT-large使用什么激活函数? => 使用的也是 GeLU(Guassian Error Linear Unit)

  2. mask的具体策略是什么?是依次针对每个token做mask吗?

  3. 训练 seq2seq LM,segment1, segment2 是如何选的呢? 难道就是相邻的两个句子吗?

Finetuning 阶段

对NLU而言,Finetune的设置与BERT相同;以分类为例,就是把[SOS] (也就是BERT里的[CLS])表示再接一个softmax layer. 更新预训练部分和softmax部分。

对NLG而言,Finetune与Pre-training是类似的!(并没有使用teacher-forcing这样的训练方式); 将输入准备为 [SOS]S1[EOS]S2[EOS]格式,然后对S2部分和S2后面的[EOS]做随机替换,让模型去预测[MASK].

疑问

对NLG,解码的时候该怎么做呢?不是auto-regressive的,难道是解码一个token就要把前面的input全部输入进去?

实验:Abstracitve Summarization任务

选取了 CNN/DM 和 Gigaword 数据集。

按照 seq2seq LM 的 finetune方式来finetune: 将 document 作为segment1, 将 summary 作为segment2. 对**合并后的输入**(需要确认)做最大长度截断。

在训练集上finetune. 大部分参数复用预训练阶段;mask概率改为0.7 (之前只有0.15). 使用 label-smoothing with rate == 0.1.

CNN/DM上,batch-size = 32, max-length = 768;

Gigaword, batch-size = 64, max-length = 256;

解码的时候:

beam-size = 5; 去除重复的trigram, 基于dev调整长度 CNN/DM, 输入文档被truncate为前640个token; Gigaword 输入被truncate为前面192个

实验:Generative QA

CoQA上,将对话历史、问题、passage拼接起来作为segment1;

如果输入超过了470长度,那么将passage在一个滑动窗口内切分几个chunk,取与question word-overlap最大的chunk作为输入。

实验:用Generative QA自动生成问题,再用自动生成的问题反过来优化QA任务

这个设计还是有点意思的;另外,还提到一句说“在数据增强的实验中,用的是bidirectional masked language model作为 辅助任务,而不是直接用(端到端的seq2seq训练?)”,这样可以获得2.3个点的绝对提升,猜测是可以避免在增强数据上灾难遗忘。

代码阅读

decode_seq2seq.py

max_seq_len 至少应该比tgt_seq_len 大2; 应该是因为seq input有额外的token;

Indices and tables