论文笔记-dynamic convolution and involution

paper list:

  • CARAFE: Content-Aware ReAssembly of FEatures
  • Involution: Inverting the Inherence of Convolution for Visual Recognition
  • Pay less attention with lightweight and dynamic convolutions
  • ConvBERT: Improving BERT with Span-based Dynamic Convolution
  • Dynamic Region-Aware Convolution
阅读更多

论文笔记-unlikelihood training

paper list:

  • Neural Text Generation with Unlikelihood Training
  • Implicit Unlikelihood Training: Improving Neural Text Generation with Reinforcement Learning
阅读更多

论文笔记-对话系统

paper

A Survey on Dialogue Systems: Recent Advances and New Frontiers, Chen et al. 2018

motivation

这是一篇关于对话系统的综述。

对话系统主要分为两大类:

  • 任务导向型(task-oriented) 对话系统

  • 非任务导向型(non-task-oriented)对话系统

    • 序列到序列模型 sequence-to-sequence models

    • 检索式模型 retrieval-based methods

task-oriented dialogue system

面向任务的系统旨在帮助用户完成实际具体的任务,例如帮助用户找寻商品,预订酒店餐厅等。

有两种方式:

  • pipeline methods

  • end-to-end methods

pipeline methods

其流程是4个步骤:

  • language understanding

  • dialogue state tracking

  • policy learning

  • natural language generation

language understanding

第一步是 utterance 理解。将给定的 utterance 映射成对应的语义槽 (semantic slots).

Given an utterance, natural language understanding maps it into semantic slots. The slots are pre-defined according to different scenarios.

slots 都是根据特定的场景定义好的。

看表格能发现,包含三个任务:

  • intent dection: 这个是 utterance-level classification,也就是一个分类任务

  • domain classification: 也是分类任务

  • slot filling: 这是 word-level 的任务,可以定义成序列标注问题,输入是一个 utterance,输出是对应每个 word 的 semantic label.

关于 slot filling 的 paper:

  • CRF baseline

  • DBNs:

    • Deep belief network based semantic taggers for spoken language understanding

    • Use of kernel deep convex networks and end-to-end learning for spoken language understanding

  • RNN:

    • Investigation of recurrent-neural-network architectures and learning methods for spoken language understanding, 2013

    • Deep belief nets for natural language call-routing. 2011

    • Recurrent neural networks for language understanding, 2013

    • Spoken language understanding using long short-term memory neural networks. 2014

Dialogue State Tracking

对话的状态跟踪,预测每一轮对话 user 的 goal. 对话状态跟踪是确保对话系统健壮性的核心组件。它在对话的每一轮次对用户的目标进行预估,管理每个回合的输入和对话历史,输出当前对话状态。这种典型的状态结构通常称为槽填充或语义框架。

所以对应的 state 是根据场景预定义好了的嘛?比如 online shopping,对应的 state 可能就有 推荐,比较,下单等等?

基于传统方法的有很多,基于 deep learning 的有:

  • [26] Deep neural network approach for the dialog state tracking challenge. 2013

  • [58] Multi-domain dialog state tracking using recurrent neural networks. 2015

  • [59] Neural belief tracker: Data-driven dialogue state tracking, 2017

Policy learning

根据上一步得到的 state,来制定下一步的 action. 很符合强化学习的理念啊,不过需要解决 热启动 (warm-start) 的问题。

  • 基于规则的监督学习(state 的状态需要规则来定义):

    • [111] Building task-oriented dialogue systems for online shopping,
  • deep reinforcement learning:

    • [14] Strategic dialogue management via deep reinforcement learning, 2015

基于强化学习的方法已经超过监督学习了。

natural language generation

一个好的生成器通常依赖于几个因素:适当性、流畅性、可读性和变化性。传统的NLG方法通常是执行句子计划。它将输入语义符号映射到代表话语的中介形式,如树状或模板结构,然后通过表面实现将中间结构转换为最终响应。深度学习比较成熟的方法是基于LSTM的encoder-decoder形式,将问题信息、语义槽值和对话行为类型结合起来生成正确的答案。同时利用了注意力机制来处理对解码器当前解码状态的关键信息,根据不同的行为类型生成不同的回复。

  • [123] Context-aware nat- ural language generation for spoken dialogue systems. Zhou et al, 2016 COLING

adopted an encoder-decoder LSTM-based structure to incorporate the question information, semantic slot values, and dialogue act type to generate correct answers. It used the attention mechanism to attend to the key information conditioned on the current decoding state of the decoder. Encoding the di- alogue act type embedding, the neural network-based model is able to generate variant answers in response to different act types.

end-to-end model

传统的 pipeline 的方法的缺点:

  • user 的反馈很难传递到每一个 module

  • 每一个 module 都是相互依赖的 (process interde- pendence)

也就是在不同的 domain 或者 scenarios 时,pipeline 设计的对话系统可能就不使用的,因为 slots 和 features 都是 task-specificed,都会相应的改变。而这些过程都需要大量的人工工程。

因此我们需要 end-to-end model。与传统的 pipeline 模型不同,端到端模型使用一个模块,并与结构化的外部数据库交互。

  • network-based end-to-end 模型需要大量的标注数据

    • Learning end-to-end goal-oriented dialog, Bordes et al, 2017 ICLR

    • A network-based end-to-end trainable task-oriented di- alogue system, 2017 ACL

  • end-to-end reinforcement learning 在对话管理中,联合训练 state tracking 和 policy learning, 从而使得模型鲁棒性更强。

    • Towards end-to-end learn- ing for dialog state tracking and management us- ing deep reinforcement learning,2016 ACL
  • task-completion neural dialogue system, 其目标就是完成一个任务。

    • End-to-end task- completion neural dialogue systems,2017

以任务为导向的对话系统通常还需要查询外部知识库。传统的采用的方法就是通过 semantic parsing 形成一个 query,然后去匹配外部知识库,通过检索得到想要的 entries. 其缺点是:

  • 检索的结果不包含有关语义分析中的不确定性信息

  • 检索的过程是不可微的 (non-differentiabl), 因此 semantic parsing 和 dialogue policy 只能分别训练,导致 online end-to-end 的模型很难部署。

解决这个问题的 paper:

Non-task-oriented dialogue system

非任务导向型对话系统也就是聊天机器人, 是通过生成模型或基于检索的方法实现的。 生成模型能够生成更合适的回复(也就是跟上下文语义更接近),而这些回复可能从来没有出现在语料库中,而基于检索的模型则能得到具有信息充裕 (informative) 和 fluent 的回复。

Neural Generative models

深度学习在机器翻译中的成功应用,即神经机器翻译,激发了人们对神经生成对话研究的热情。

最开始也有一篇 paper,将对话当最机器翻译来做的 paper. 把对话看作是将 post 翻译成 response。但是区别在于 response 的范围很广,而且 post 和 response 并不像翻译的两个句子之间存在对齐关系。

目前神经生成模型的热门研究课题,主要是讨论:

  • response diversity

  • modeling topics and personalities

  • leveraging outside knowledge base

  • the interactive learning

  • evaluation

Sequence-to-Sequence Models

这个就是基本的 seq2seq 模型。好奇的是,如何解决多轮对话,如何结合 history 信息,如何控制对话的状态,这些都需要深入看 paper 吧。

Dialogue Context

考虑历史对话的历史信息的能力是建立可保持对话活跃的对话系统的关键。

Response Diversity

A challenging problem in current sequence-to-sequence dialogue systems is that they tend to generate trivial or non-committal, universally relevant responses with little meaning, which are often involving high frequency phrases along the lines of I dont know or Im OK.

在当前的序列对话系统中,一个具有挑战性的问题是,它们倾向于产生意义不大的普通或不重要的、普适的回答,而这些回答往往涉及到“我不知道”或者“我很好”这样的高频率短语。

  1. MMI and IDF

模型的这种行为可以归咎于模型赋予了 “safe” response 更高的概率。A diversity-promoting objective function for neural con- versation models. ACL 2016 使用了 Maximum Mutual Information 作为优化目标,这是最初在语音识别领域引入的。 它测量了输入和输出之间的相互依赖关系,并考虑了消息回复的逆向依赖性。 An attentional neural conversation model with improved speci- ficit, 2016 结合逆文档频率(IDF)到训练过程来评价回复的多样性。(在不同的 document 中出现的回复次数越多,其相应的权重越低)。

  1. beam-search

一些研究表明,解码的过程也是回复冗余的另一个缘由。[86][72][42] 发现 beam-search 在生成候选答案时中缺乏多样性。[86] 提出了一种衡量不同回复之间的相似度的方法,类似于正则惩罚项吧,来增强 beam-search 的目标函数。[72] 提出了一种随机 beam-search 的方法,[42] 则使用了一个惩罚项来惩罚来自同一父节点中的子节点的展开。

  1. re-ranking

[38][77][72] 结合全局特征,重新执行 re-ranking 的步骤,从而避免生成 dull or generic 的回复。

  1. PMI

[57] 猜测问题不仅仅在于解码和 respones 的频率,而且消息本身也缺乏足够的信息。 它提出使用逐点互信息(PMI)来预测名词作为关键词,反映答复的主要依据,然后生成一个包含给定关键字的答复.

  1. latent variable

另一系列工作着重于通过引入随机隐变量来产生更多不同的输出。 他们表明,自然对话不是确定性的 —— 对同一信息的答复可能会因人而异。 但是,当前回复是从确定性 encoder-decoder 模型中采样的。 通过整合隐变量,这些模型的优点是,在生成时,他们可以通过首先对隐变量的分配进行采样,然后确定性地进行解码,从分布中采样回复。

Topic and Personality

明确对话的内在属性是提高对话多样性和保证一致性的另一种方法。在不同的属性中,主题和个性被广泛地进行研究探讨。

  1. Topic aware neural response generation, AAAI 2017 注意到人们经常把他们的对话与主题相关的概念联系起来,并根据这些概念做出他们的回复。他们使用Twitter LDA模型来获取输入的主题,将主题信息和输入表示输入到一个联合注意模块中,并生成与主题相关的响应。
  1. Multiresolution recurrent neural networks: An application to dialogue response generation. AAAI 2017 对粗粒度的 tokens sequence 和 dialogue generation 进行联合建模,粗粒度的 tokens 主要是用来探索 high-level 的语义信息,通常是 name entity 或 nouns.
  1. Emotional chatting machine: Emotional conversation generation with internal and external memory 将情感 embedding 融入到了对话生成中。Affective neural response generation, 2017 通过三种方式增强回复的情感:
  • incorporating cognitive engineered affective word embeddings

  • augmenting the loss objective with an affect-constrained objective function

  • injecting affective dissimilarity in diverse beam-search inference procedure

  1. Assigning personality/identity to a chatting machine for coherent conversation generation 让对话个性化,并且保持一致性。Neural per- sonalized response generation as domain adaptation 提出了一种两阶段的训练方法,使用大规模数据对模型进行初始化,然后对模型进行微调,生成个性化响应。
  1. Personalizing a dialogue system with transfer reinforcement learning 使用强化学习来消除对话的前后不一致性。

Outside Knowledge Base

人类对话与对话系统之间的一个重要区别是它是否与现实相结合。结合外部知识库(KB)是一种很有前途的方法,可以弥补背景知识之间的差距,即对话系统和人之间的差距。记忆网络(Memory Network)是一种以知识库处理问题的经典方法。因此,它非常直接的别用于在对话生成中。实际研究表明,所提出的模型能够通过参考知识库中的事实来生成对问题的自然和正确答案。

Interactive Dialogue learning

通过交互来学习是对话系统的最终目标之一。Deep reinforcement learning for dialogue generation, ACL 2016 利用两个虚拟智能体模拟对话。它们定义了对描述一个较好的对话的汇报的一个简单的启发式的估计:好的对话是有前瞻性[1]或者交互式的(当前轮为下一轮对话铺垫),是信息丰富的和连贯的。一个RNN的编码器-解码器所有参数定义了一个在无穷大的动作空间上从所有可能的话语中进行选择的策略。智能体是通过策略梯度方法 Simple statistical gradient-following al- gorithms for connectionist reinforcement learning, 1992 来优化由开发者定义的长期奖励,而不是通过标准seq2seq的MLE目标函数来学习策略。[32]进一步试图提高机器人从交互中学习的能力。通过对文本和数字反馈使用策略学习和前向预测,该模型可以通过(半)在线方式与人进行交互来提高自身性能。

由于大多数人类在对答案并不自信时通常会要求提供一些澄清或者提示,所有机器人拥有这种能力也是相当自然的。Learning through dialogue interactions by asking questions. 2017 定义了机器人在回答问题时遇到困难时的三种情况。与不采用提问的实验结果相比,这种方法在一些情况下有了很大的改进。Deal or no deal? end-to-end learning of negotiation dialogues, ACL 2017 在谈判任务中进行了探索。由于传统的序列到序列模型模拟人类的对话没有优化具体的目标,这项工作采取了面向目标的训练和解码方法,并展示了一个有价值的视角。

Evaluation

评价生成回复的质量是对话系统的一个重要方面。任务导向型的对话系统可以基于人工生成的监督信号进行评估,例如任务完成测试或用户满意度评分等,然而,由于高回复的多样性,自动评估非任务导向的对话系统所产生的响应的质量仍然是一个悬而未决的问题。目前的方法有以下几种:

  • BLEU, METEOR, and ROUGE 值,也就是直接计算 word overlap、ground truth和你生成的回复。由于一句话可能存在多种回复,因此从某些方面来看,BLEU 可能不太适用于对话评测。

  • 计算 embedding的距离,这类方法分三种情况:直接相加求平均、先取绝对值再求平均和贪婪匹配。

  • 进行图灵测试,用 retrieval 的 discriminator 来评价回复生成。

Retrieval-based Methods

基于检索的方法从候选回复中选择回复。检索方法的关键是消息-回复匹配,匹配算法必须克服消息和回复之间的语义鸿沟。

single-turn response match

$$match(x,y)=x^TAy$$

Convolutional neu- ral network architectures for matching natural lan- guage sentences, 2014 利用深度卷积神经网络体系结构改进模型,学习消息和响应的表示,或直接学习两个句子的相互作用表示,然后用多层感知器来计算匹配的分数。

multi-turn response

Hybrid Methods

将生成和检索方法结合起来能对系统性能起到显著的提升作用。基于检索的系统通常给出精确但是较为生硬的答案,而基于生成的系统则倾向于给出流畅但却是毫无意义的回答。在集成模型中,被抽取的候选对象和原始消息一起被输入到基于RNN的回复生成器中。这种方法结合了检索和生成模型的优点,这在性能上具备很大的优势。

展望

端到端的框架不仅在非面向任务的聊天对话系统中流行,而且在面向任务的对话系统中逐步流行起来。深度学习能够利用大量的数据,从而模糊了任务导向型对话系统和非任务导向型对话系统之间的界限。值得注意的是,目前的端到端模型仍然远非完美。尽管取得了上述成就,但这些问题仍然具有挑战性。接下来,我们将讨论一些可能的研究方向。

  • Swift Warm-Up,在一些新的领域,特定领域对话数据的收集和对话系统的构建是比较困难的。未来的趋势是对话模型有能力从与人的交互中主动去学习。
  • Deep Understanding. 深度理解。现阶段基于神经网络的对话系统极大地依赖于大量标注好的数据,结构化的知识库以及对话语料数据。在某种意义上产生的回复仍然缺乏多样性,有时并没有太多的意义,因此对话系统必须能够更加有效地深度理解语言和真实世界。
  • Privacy Protection. 目前广泛应用的对话系统服务于越来越多的人。很有必要注意到的事实是我们使用的是同一个对话助手。通过互动、理解和推理的学习能力,对话助手可以无意中隐蔽地存储一些较为敏感的信息。因此,在构建更好的对话机制时,保护用户的隐私是非常重要的。

论文笔记-预训练语言模型2-ULMFiT

Motivation

对比之前的几种模型

concatenate embeddings: ELMo

Recent approaches that concatenate embeddings derived from other tasks with the input at different layers (Peters et al., 2017; McCann et al., 2017; Peters et al., 2018) still train the main task model from scratch and treat pretrained embeddings as fixed parameters, limiting their usefulness.

这篇 paper 是在 elmo 之后,而 elmo 虽然相对出名,影响力更大,但是 elmo 仍旧只是一种 word embedding 的预训练,在下游任务中还是需要从头训练模型。

ELMo有以下几个步骤:

  • 利用LM任务进行预训练

  • 再利用目标领域的语料对LM模型做微调

  • 最后针对目标任务进行 concatenate embedding,然后训练模型

pretraining LM:

In light of the benefits of pretraining (Erhan et al., 2010), we should be able to do better than randomly initializing the remaining parameters of our models. However, inductive transfer via finetuning has been unsuccessful for NLP (Mou et al., 2016). Dai and Le (2015) first proposed finetuning a language model (LM) but require millions of in-domain documents to achieve good performance, which severely limits its applicability.

直接使用在 general-domain 上预训练好的语言模型,然后通过 fine-tune 进行迁移学习, 仍旧需要大量的 in-domain 的文档才能获得比较好的 performance.

ULMFiT

We show that not the idea of LM fine-tuning but our lack of knowledge of how to train them effectively has been hindering wider adoption. LMs overfit to small datasets and suffered catastrophic forgetting when fine-tuned with a classifier. Compared to CV, NLP models are typically more shallow and thus require different fine-tuning methods.

作者认为,预训练语言模型的方式并不是不好,只是训练方法的问题导致了他们表现局限性。想对于 CV, NLP 中的很多任务所需要的语义更浅层。而将 LMs 在小数据集上 fine-tune 时会导致严重的遗忘。

于是,作者提出了 Universal Language Model Fine-tuning(ULMFiT)

  • 通用的语言模型微调

  • discriminative fine-tuning, slanted triangular learning rates

  • gradual unfreezing

Universal Language Model Fine-tuning

主要分为 3 部分:

  • General-domain LM pretraining

  • Target task LM fine-tuning

  • Target task classifier fine-tuning

General-domain LM pretraining

Wikitext-103 (Merity et al., 2017b) consisting of 28,595 preprocessed Wikipedia articles and 103 million words.

在足够大的 general-domain 语料库上进行预训练。

Target task LM fine-tuning

discriminative fine-tunin

在目标语料库 in-domain 上进行 fine-tune. 这部分会收敛的很快,并且在小数据集上依旧会有很好的泛化性。

As different layers capture different types of information (Yosinski et al., 2014), they should be fine-tuned to different extents.

不同的 layer 能捕捉不同程度的信息,于是,作者提出了 discriminative fine-tuning. 不同的 layer 具有不同的 learning rate. L 表示总的 layer 数目。

$${\theta^1,\theta^2, …, \theta^L}$$

$${\eta^1,\eta^2, …, \eta^L}$$

Instead of using the same learning rate for all layers of the model, discriminative fine-tuning allows us to tune each layer with different learning rates.

原本的 SGD 是这样的:

$$\theta_t = \theta_{t-1}-\eta\cdot\nabla_{\theta}J(\theta)$$

改进之后:

$$\theta_t^l = \theta_{t-1}^l-\eta^l\cdot\nabla_{\theta^l}J(\theta)$$

作者通过经验发现:先选择最后一层的学习率 $\eta^L$,然后计算每一层的学习率 $\eta^{l-1}=\eta^l/2.6$

Slanted triangular learning rates

  • T 是迭代次数,这里实际上是 $epochs \times \text{number of per epoch}$

  • cut_frac 是增加学习率的迭代步数比例

  • cut 是学习率增加和减少的临界迭代步数

  • p 是一个分段函数,分别递增和递减

  • ratio 表示学习率最小时,与最大学习率的比例。比如 t=0时,p=0, 那么 $\eta_0=\dfrac{\eta_{max}}{ratio}$

作者通过实验发现,cut_frac=0.1, ratio=32, $\eta_max=0.01$

Target task classifier fine-tuning

针对分类任务,加上 two additional linear blocks.

concat pooling

gradul unfreezing

逐渐 unfreeze layers:

We first unfreeze the last layer and fine-tune all unfrozen layers for one epoch. We then unfreeze the next lower frozen layer and repeat, until we finetune all layers until convergence at the last iteration.

BPTT for Text Classification

backpropagation through time(BPTT)

We divide the document into fixed length batches of size b. At the beginning of each batch, the model is initialized with the final state of the previous batch; we keep track of the hidden states for mean and max-pooling; gradients are back-propagated to the batches whose hidden states contributed to the final prediction. In practice, we use variable length backpropagation sequences (Merity et al., 2017a).

什么意思?并不是一个 batch 更新一次梯度,而是累加一定的 batch 之后在更新梯度?

能增加泛化性?

Bidirectional language model

独立的对 forward-LM, backward-LM 进行 fine-tune, 然后平均。

experiment

与其他模型对比

ablations

“from scratch”: 没有 fine-tune

“supervised”: 表示仅仅在 label examples 进行 fine-tune

“semi-supervised”: 表示在 unable examples 上也进行了 fine-tune

对 tricks 进行分析

“full” :fine-tuning the full model

“discr”: discriminative fine-tuning

“stlr”: slanted triangular learning rates

论文笔记-BERT

BERT(Bidirectional Encoder Representations from Transformers.)

对于 BERT 重点在于理解 Bidirectional 和 masked language model.

Why Bidirectional?

对于预训练的表示,单向语言模型因为无法融合下文的信息,其能力是非常有限的,尤其是对类似于 SQuAD 这样需要结合上下文信息的任务。

对比 OpenAI GPT 和 BERT. 为什么 OpenAI GPT 不能采用双向 self-attention 呢?

传统的语言模型的定义,计算句子的概率:

$$P(S)=p(w_1,w_2, …, w_n)=p(w1)p(w_2|w_1)…p(w_n|w_1…w_{n-1})=\prod_{i=1}^m p(w_i|w_1…w_{i-1})$$

前向 RNN 语言模型:

$$P(S)=\prod_{i=1}^m p(w_i|w_1…w_{i-1})$$

也就是当前词的概率只依赖前面出现词的概率。

后向 RNN 语言模型

$$P(S)=\prod_{i=1}^m p(w_i|w_{i+1}…w_{m})$$

也就是当前词的概率只依赖后面出现的词的概率。

ELMo 就是这样的双向语言模型(BiLM)

但是 RNN 相比 self-attention 对上下文信息 (contextual information)的利用相对有限,而且 ELMo 只能是一层双向,并不能使用多层。其原因和 GPT 无法使用 双向 编码的原因一样。

对于 GPT 如果它使用双向,那么模型就能准确的学到到句子中的下一个词是什么,并能 100% 的预测出下一个词。比如 “I love to work on NLP.” 在预测 love 的下一个词时,模型能看到 to,所以能很快的通过迭代学习到 “to” 100% 就是 love 的下一个词。所以,这导致模型并不能学到想要的东西(句法、语义信息)。

那么 BERT 是怎么处理双向这个问题的呢? 它改变了训练语言模型的任务形式。提出了两种方式 “masked language model” and “next sentence generation”. 再介绍这两种训练方式之前,先说明下输入形式。

Input representation

  • position embedding: 跟 Transformer 类似

  • sentence embedding, 同一个句子的词的表示一样,都是 $E_A$ 或 $E_B$. 用来表示不同的句子具有不同的含义

  • 对于 [Question, Answer] 这样的 sentence-pairs 的任务,在句子末尾加上 [SEP].

  • 对于文本分类这样的 single-sentence 的任务,只需要加上 [CLS], 并且 sentence embedding 只有 $E_A$.

masked language model

何为 “masked LM”? idea 来源于 closed tasked. 原本的语言模型是预测所有语料中的下一个词,而 MLM 是在所有的 tokens 中随机选取 15% 的进行 mask,然后只需要预测被 mask 的词。这样以来,就能训练双向语言模型了。

但是存在一个问题,这样 pre-training 训练出来的语言模型并不能拿去做 fine-tune. 原因是在 fine-token 中从来没有见过 <MASK> 这个词。作者采用这样的策略:

具体的操作,以 “My dog is hairy” 为例,mask “hairy” 这个词:

  • “My dog is <MASK>“. 80% 被 代替

  • “My dog is apple”. 10% 被一个随机的 token 代替

  • “My dog is hairy”. 10% 保持原来的样子

为什么不用 <MASK> 代替所有的 token?

If the model had been trained on only predicting ‘<MASK>’ tokens and then never saw this token during fine-tuning, it would have thought that there was no need to predict anything and this would have hampered performance. Furthermore, the model would have only learned a contextual representation of the ‘<MASK>’ token and this would have made it learn slowly (since only 15% of the input tokens are masked). By sometimes asking it to predict a word in a position that did not have a ‘<MASK>’ token, the model needed to learn a contextual representation of all the words in the input sentence, just in case it was asked to predict them afterwards.

如果模型在预训练的时候仅仅只预测 <MASK>, 然后在 fine-tune 的时候从未见过 <MASK> 这个词,那么模型就不需要预测任何词,在 fine-tune 时会影响性能。

更严重的是,如果仅仅预测 <MASK>, 那么模型只需要学习 <MASK> 的上下文表示,这会导致它学习的很慢。

如果让模型在某个位置去预测一个不是 <MASK> 的词,那么模型就需要学习所有 tokens 的上下文表示,因为万一需要预测这个词呢。

只需要 random tokens 足够吗?为什么还需要 10% 的完整的 sentence?

Well, ideally we want the model’s representation of the masked token to be better than random. By sometimes keeping the sentence intact (while still asking the model to predict the chosen token) the authors biased the model to learn a meaningful representation of the masked tokens.

使得模型具有偏置,更倾向于获得有意义的 masked token.

在知乎上问了这个问题,大佬的回复跟这篇 blog 有点差异,但实际上意思是一样的:

总结下:

为什么不能完全只有 <MASK> ? 如果只有 <MASK>, 那么这个预训练模型是有偏置的,也就是学到一种方式,用上下文去预测一个词。这导致在 fine-tune 时,会丢一部分信息,也就是知乎大佬第一部分所说的。

所以加上 random 和 ture token 是让模型知道,每个词都是有意义的,除了上下文信息,还要用到它本身的信息,即使是 <MASK>. 也就是知乎上说的,提取这两方面的信息。

再回过头,从语言模型的角度来看,依然是需要预测每一个词,但是绝大多数词它的 cross entropy loss 会很小,而主要去优化得到 <MASK> 对应的词。而 random/true token 告诉模型,你需要提防每一个词,他们也需要好好预测,因为他们不一定就是对的。

感谢知乎大佬!

random tokens 会 confuse 模型吗?

不会, random tokens 只占 15% * 10% = 1.5%. 这不会影响模型的性能。

还有一个问题, <MASK> 所占的比例很小,主要优化对象迭代一次对整个模型影响会很小,因而需要更多次迭代.

next sentence generation

对于下游是 Question Answering(QA), Natural Language Inference(NLI) 这样需要理解句子之间的相关性的任务,仅仅通过语言模型并不能获得这方面的信息。为了让模型能够理解句子之间的关系,作者提出了一个 binarized next sentence prediction.

具体方式是:

50% 是正确的相邻的句子。 50% 是随机选取的一个句子。这个任务在预训练中能达到 97%-98% 的准确率,并且能很显著的提高 QA NLI 的任务。

pre-training procudure

作者预训练使用的语料:BooksCorpus (800M words),English Wikipedia (2,500M words)。 使用文档级别的语料很关键,而不是 shffule 的句子级别的语料,这样可以获得更长的 sentence.

获得训练样本:从预料库中抽取句子对,其中 50% 的两个句子之间是确实相邻的,50% 的第二个句子是随机抽取的。具体操作看代码吧

  • batch_size 256.

  • 每一个 sentences 对: 512 tokens

  • 40 epochs

  • Adam lr=1e-4, $\beta_1=0.9$, $\beta_2=0.999$, L2 weight decay 0.01

  • learning rate warmup 10000 steps

  • 0.1 dropout

  • gelu instead of relu

Fine-tune procedure

sequence-level tasks

  • 比如 sentences pairs 的 Quora Question Pairs(QQP) 预测两个句子之间语义是否相同。如下图中(a).

  • 如果是 single sentence classification 比如 Stanford Sentiment Treebank(SST-2)和 Corpus of Linguistic Acceptability(CoLA)这种分类问题。如下图(b)

只需要输出 Transformer 最后一层的隐藏状态中的第一个 token,也就是 [CLS]. 然后接上一个全链接映射到相应的 label 空间即可。

fine-tune 时的超参数跟 pre-training 时的参数大致相同。但是训练速度会很快

  • Batch size: 16, 32

  • Learning rate (Adam): 5e-5, 3e-5, 2e-5

  • Number of epochs: 3, 4

语料库越大,对参数的敏感度越小。

token-level tasks.

对于token-level classification(例如NER),取所有token的最后层transformer输出,喂给softmax层做分类。

如何使用 BERT

文本分类

https://github.com/huggingface/pytorch-pretrained-BERT/blob/master/examples/run_classifier.py

主要涉及到两个 类:

  • 数据预处理

  • 预训练模型加载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

from pytorch_pretrained_bert import BertTokenizer, BertForSequenceClassification, BertConfig, BertAdam, PYTORCH_PRETRAINED_BERT_CACHE



tokenizer = BertTokenizer.from_pretrained(args.bert_model, do_lower_case=args.do_lower_case)

tokenizer = BertTokenizer.from_pretrained("./pre_trained_models/bert-base-uncased-vocab.txt")



model = BertForSequenceClassification.from_pretrained('bert-base-uncased',

cache_dir=PYTORCH_PRETRAINED_BERT_CACHE / 'distributed_{}'.format(args.local_rank),

num_labels = num_labels)

model = BertForSequenceClassification.from_pretrained("pre_trained_models/bert-base-uncased.tar.gz", num_labels=2)

其中 bert-base-uncased 可以分别用具体的 词表文件 和 模型文件 代替。从源代码中提供的链接下载即可。

数据处理

1
2
3
4
5
6
7
8
9

from pytorch_pretrained_bert import BertTokenizer, BertForSequenceClassification, BertConfig, BertAdam, PYTORCH_PRETRAINED_BERT_CACHE



tokenizer = BertTokenizer.from_pretrained(args.bert_model, do_lower_case=args.do_lower_case)

tokenizer = BertTokenizer.from_pretrained("./pre_trained_models/bert-base-uncased-vocab.txt")

前一种方式是根据代码中提供的 url 去下载词表文件,然后缓存在默认文件夹下 /home/panxie/.pytorch_pretrained_bert 。后者是直接下载词表文件后,放在本地。相对来说,后者更方便。

这部分代码相对比较简单,根据自己的任务,继承 DataProcessor 这个类即可。

作为模型的输入,features 主要包括三个部分:

  • input_ids 是通过词典映射来的

  • input_mask 在 fine-tune 阶段,所有的词都是 1, padding 的是 0

  • segment_ids 在 text_a 中是 0, 在 text_b 中是 1, padding 的是 0

这里对应了前面所说的,input_idx 就是 token embedding, segment_ids 就是 Sentence Embedding. 而 input_mask 则表示哪些位置被 mask 了,在 fine-tune 阶段都是 1.

加载预训练模型

1
2
3
4
5
6
7
8
9

!tar -tf pre_trained_models/bert-base-uncased.tar.gz



./pytorch_model.bin

./bert_config.json

下载好的文件包中含有两个文件,分别是 config 信息,以及模型参数。

如果不用具体的文件,则需要从代码中提供的 url 下载,并缓存在默认文件夹 PYTORCH_PRETRAINED_BERT_CACHE = /home/panxie/.pytorch_pretrained_bert

作为分类任务, num_labels 参数默认为 2.

运行时会发现提取预训练模型会输出如下信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

12/26/2018 17:00:41 - INFO - pytorch_pretrained_bert.modeling -

loading archive file pre_trained_models/bert-base-uncased.tar.gz

12/26/2018 17:00:41 - INFO - pytorch_pretrained_bert.modeling -

extracting archive file pre_trained_models/bert-base-uncased.tar.gz to temp dir /tmp/tmpgm506dcx

12/26/2018 17:00:44 - INFO - pytorch_pretrained_bert.modeling -

Model config {

"attention_probs_dropout_prob": 0.1,

"hidden_act": "gelu",

"hidden_dropout_prob": 0.1,

"hidden_size": 768,

"initializer_range": 0.02,

"intermediate_size": 3072,

"max_position_embeddings": 512,

"num_attention_heads": 12,

"num_hidden_layers": 12,

"type_vocab_size": 2,

"vocab_size": 30522

}



12/26/2018 17:00:45 - INFO - pytorch_pretrained_bert.modeling -

Weights of BertForSequenceClassification not initialized from pretrained model:

['classifier.weight', 'classifier.bias']

12/26/2018 17:00:45 - INFO - pytorch_pretrained_bert.modeling -

Weights from pretrained model not used in BertForSequenceClassification:

['cls.predictions.bias', 'cls.predictions.transform.dense.weight',

'cls.predictions.transform.dense.bias', 'cls.predictions.decoder.weight',

'cls.seq_relationship.weight', 'cls.seq_relationship.bias',

'cls.predictions.transform.LayerNorm.weight', 'cls.predictions.transform.LayerNorm.bias']

不得不去观察 from_pretrained 的源码:https://github.com/huggingface/pytorch-pretrained-BERT/blob/8da280ebbeca5ebd7561fd05af78c65df9161f92/pytorch_pretrained_bert/modeling.py#L448

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

missing_keys = []

unexpected_keys = []

error_msgs = []

# copy state_dict so _load_from_state_dict can modify it

metadata = getattr(state_dict, '_metadata', None)

state_dict = state_dict.copy()

if metadata is not None:

state_dict._metadata = metadata



def load(module, prefix=''):

local_metadata = {} if metadata is None else metadata.get(prefix[:-1], {})

module._load_from_state_dict(

state_dict, prefix, local_metadata, True, missing_keys, unexpected_keys, error_msgs)

for name, child in module._modules.items():

if child is not None:

load(child, prefix + name + '.')

load(model, prefix='' if hasattr(model, 'bert') else 'bert.')

if len(missing_keys) > 0:

logger.info("Weights of {} not initialized from pretrained model: {}".format(

model.__class__.__name__, missing_keys))

if len(unexpected_keys) > 0:

logger.info("Weights from pretrained model not used in {}: {}".format(

model.__class__.__name__, unexpected_keys))

if tempdir:

# Clean up temp dir

shutil.rmtree(tempdir)

return model

这部分内容解释了如何提取模型的部分参数.

missing_keys 这里是没有从预训练模型提取参数的部分,也就是 classifier ['classifier.weight', 'classifier.bias']层,因为这一层是分类任务独有的。

unexpected_keys 则是对于分类任务不需要的,但是在预训练的语言模型中是存在的。查看 BertForMaskedLM 的模型就能看到,cls 层,是专属于语言模型的,在下游任务中都需要去掉。

所以这部分代码实际上学到了如何选择预训练模型的部分参数~~棒啊!

论文笔记-character embedding and ELMO

character embedding

Motivation

A language model is formalized as a probability distribution over a sequence of strings (words), and traditional methods usually involve making an n-th order Markov assumption and estimating n-gram probabilities via counting and subsequent smoothing (Chen and Goodman 1998). The count-based models are simple to train, but probabilities of rare n-grams can be poorly estimated due to data sparsity (despite smoothing techniques).

对语言模型的描述:语言模型是 一个单词序列的概率分布 的形式化描述(什么意思?就是比如这个句子长度为 10, 那么每个位置可能是词表中的任意一个词,而出现当前词是有一个概率的, 这个概率是依赖于之前的词的)。

在传统的方法主要是运用 n阶马尔可夫假设来估计 n-gram 的概率,通过统计计数,以及子序列平滑的方式。这种基于计数的模型虽然简单,但是在数据稀疏的情况下,对不常见的 n-gram 的概率估计会很差。

While NLMs have been shown to outperform count-based n-gram language models (Mikolov et al. 2011), they are blind to subword information (e.g. morphemes). For example, they do not know, a priori, that eventful, eventfully, uneventful, and uneventfully should have structurally related embeddings in the vector space. Embeddings of rare words can thus be poorly estimated, leading to high perplexities for rare words (and words surrounding them). This is especially problematic in morphologically rich languages with long-tailed frequency distributions or domains with dynamic vocabularies (e.g. social media).

neural language models 将词嵌入到低维的向量中,使得语义相似的词在向量空间的位置也是相近的。然后 Mikolov word2vec 这种方式不能有效的解决子单词的信息问题,比如一个单词的各种形态,也不能认识前缀。这种情况下,不可避免的会造成不常见词的向量表示估计很差,对于不常见词会有较高的困惑度。这对于词语形态很丰富的语言是一个难题,同样这种问题也是动态词表的问题所在(比如社交媒体)。

Recurrent Neural Network Language Model

给定词表为 V,之前的序列是 $w_{1:t}=[w_1,..,w_t]$,在 RNN-LM 中通过全链接 affine transformation 计算 $w_{t+1}$ 个词的概率分布:

$$Pr(w_{t+1}=j|w_{1:t})=\dfrac{exp(h_t\cdot p^j+q^j)}{\sum_{j’\in V}exp(h_t\cdot p^{j’}+q^{j’})}$$

其中 $h_t$ 是当前 t 时刻的隐藏状态。也就是先通过全链接映射到词表的 V 的维度,然后通过 softmax 计算其是词表中第 j 个词的概率。

然后假设训练预料库的 sentence 是 $w_{1:T}=[w_1,…,w_T]$,那么训练也就是最小化这个序列的 似然概率的负对数:

$$NLL=-\sum_{T}^{t=1}logPr(w_t|w_{1:t-1})$$

Chracter-level Convolution Neural Network

以单词 absurdity 为例,有 l 个字符(通常会 padded 到一个固定size),通过 character embedding 映射成矩阵 $C\in R^{d\times l}$. d 是 embedding size. 图中 embedding size 为 4.

然后使用卷积核 kernel H 做卷积运算, $H\in R^{d\times w}$,所以得到的 feature map $f^k\in R^{l-w+1}$. 跟之前 CNN 做文本分类其实挺像的, kernel 的长是 embedding size d, 宽度 w 分别是 2,3,4. 上图中蓝色区域为例,filter 宽度为 2 的个数是3, 那么卷积得到的 featur map 是 $3 \times (9-2+1) = 3\times 8$.

$$f^k[i]=tanh(<C^k[* ,i:i-w+1], H> +b)$$

<>表示做卷积运算(Frobenius inner product). 然后加上 bias 和 非线性激活函数 tanh.

接着基于 times 维度做 max pooling. 上图中 filter 宽度为 3,2,4 的个数分别为 4,3,5.所以得到长度为 4+3+5=12 的向量。

这里每一个 filter matrix 得到一个相应的特征 feature. 在通常的 NLP 任务中这些 filter 的总数 $h\in[100, 1000]$

Highway Network

通过卷积层得到单词 k 的向量表示为 $y^k$.

Highway Network 分为两层 layer.

  • one layer of an MLP applies an affine transformation:

$$z=g(W_y+b)$$

  • one layer 有点类似 LSTM 中的 gate 机制:

$$z=t\circ g(W_Hy+b_H)+(1-t)\circ y$$

其中 g 是非线性函数。$t=\sigma(W_Ty+b_T)$. t 成为 transform gate, (1-t) 是 carry gate. 同 LSTM 类似, highway network 允许输出能自适应的从 $y^k$ 中直接获取信息。

ELMo

传统的提取 word embedding 的方法,比如 word2vec 和 language model, 前者是通过词与词之间的共现,后者是 contextual,但他们都是获得固定的 embedding,也就是每一个词对应一个单一的 embedding. 而对于多义词显然这种做法不符合直觉, 而单词的意思又和上下文相关, ELMo的做法是我们只预训练 language model, 而 word embedding 是通过输入的句子实时输出的, 这样单词的意思就是上下文相关的了, 这样就很大程度上缓解了歧义的发生. 且 ELMo 输出多个层的 embedding 表示, 试验中已经发现每层 LM 输出的信息对于不同的任务效果不同, 因此对每个 token 用不同层 embedding 表示会提升效果.

个人觉得,可以从这个角度去理解。RNN 可以看做一个高阶马尔可夫链,而不同于 马尔可夫模型,RNN 中的状态转移矩阵是用神经网络来模拟的,也就是我们计算隐藏层所用的 $h_t=tanh(w_{hh}h_{t-1}+w_{hx}x_t)$. 这个状态转移是动态的,也是不断更新的。而使用 语言模型 来训练 RNN/LSTM 目的就是得到这样的一套参数,使得它能学习到任何 合理的,自然的 sentence. 所以,这个语料库越大越好。事实上,有监督的训练也可以达到这个目的,但是有监督的数据有限,并且整个模型是有偏置的,比如文本分类的任务去训练,那么它更倾向于 局部信息。相比之下,机器翻译作为有监督的效果会更好,最好的还是语言模型呢,不仅可用的数据量很大,而且因为要预测每一个词的信息,它会努力结合每一个词的上下文去学习这个词的表示。这也正是我们需要的。ELMo 和 BERT 都是这样的道理,而 BERT 的优势前一篇 blog 说过了。

Bidirectional language models

给定 sentence $t_1, t_2,…,t_N$, 通过前面的词 $t_1,..,t_{k-1}$ 计算 token $t_k$ 的概率分布:

反向:

语言模型的训练就是采用极大似然估计,最大化这个概率:

传统的方法就是 提取出对应位置的向量表示作为对应位置的词向量 context-independent token representation $x_k^{LM}$.

ELMo

ELMo is a task specific combination of the intermediate layer representations in the biLM.

ELMo 实际上只是下游任务的中间层,跟 BERT 一样。但也有不同的是, ELMo 每一层的向量表示会获得不同的 信息。底层更能捕捉 syntax and semantics 信息,更适用于 part-of-speech tagging 任务,高层更能获得 contextual 信息,更适用于 word sense disambiguation 任务。所以对不同的任务,会对不同层的向量表示的利用不同。

在使用 ELMo 进行下游有监督训练时,通常是这样 $[x_k; ELMo_k^{task}]$. 对于 SQuAD 这样的任务,$[h_k, ELMo_k^{task}]$.

Model architecture

The final model uses L = 2 biLSTM layers with 4096 units and 512 dimension projections and a residual connection from the first to second

layer. The context insensitive type representation uses 2048 character n-gram convolutional filters followed by two highway layers and a linear projection down to a 512 representation.

具体模型还是得看代码。