论文阅读W19-4423——预训练与迁移学习在GEC的应用
Posted 囚生CY
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了论文阅读W19-4423——预训练与迁移学习在GEC的应用相关的知识,希望对你有一定的参考价值。
本文依然在CONLL2014的最新进展网站上可以下载获得https://nlpprogress.com/english/grammatical_error_correction.html
与以前的方法有所创新的地方在于,本文着重使用了预训练的语言模型,并且采取了Denoising AutoEncoders(DAEs)方法,取得的效果是极其卓越的。并且在本文对应的代码中(在上面的网址中有Github下载链接https://github.com/kakaobrain/helo_word/),作者给出了所有用到的公开数据集的下载链接,写在了preprocess.py文件中,虽然部分需要翻墙获得,但是有来源总比到处找不到来得强。
总之GEC肯定训练集越多越好,模型就只能听天由命了。
A Neural Grammatical Error Correction System Built On Better Pre-training and Sequential Transfer Learning
【摘要】
1. GEC可以视为一个低资源(low-resource)的seq2seq任务, 因为目前公开可以获得的平行语料有限;
2. 为了处理这个挑战, 我们使用一个事实噪声函数(realistic noising function)从大规模未标注的语料集生成错误版本的语料;
3. 平行语料用于预训练Transformer模型;
4. 通过迁移学习我们将这些模型用于测试集;
5. 结合了一个上下文感知的神经拼写检查器(context-aware neural spellchecker, 下文简称CANS), 我们在ACL2019_BEA_shared_task取得了很好的成绩;
6. 代码已开源;
# 1 Introduction
1. 一些前人的方法:
- 基于短语的统计机器翻译(phrase-based statistical machine translation, PBSMT);
- 神经机器翻译(NMT);
- 因为GEC是一个低资源性的任务, 因此近期的GEC模型大都融合了语言模型(LM), 文本编校(text revision), 降噪处理(denoising);
2. 本文的贡献: 一个融合了预训练和迁移学习的GEC模型
- 在降噪任务上使用了一个新颖的噪声函数来预训练我们的模型, 这给我们一个包含真实语法错误的平行语料;
- 我们使用序列迁移学习的方法, 因此有效地将我们的预训练模型使用到该任务中;
- 我们引入CANS, 它通过使用一个预训练的神经语言模型来将上下文吸收进拼写检查器, 从而提升了模型效果(spellchecker是流行的);
# 2 Background
## 2.1 Transformers
1. Transformer的结构介绍:
- encoder: 多头自注意机制-->前馈神经网络(position-wise)-->残差连接-->层标准化;
- decoder: 每个decoder在它的多头自注意机制与前馈神经网络间还加入了encoder的输出;
- 每个输入token结合了它自身的位置编码(position-embedding);
## 2.2 Copy-Augmented Transformers (CAT)
1. 复制增强Transformers(下文简称CAT)是一类包含基于attention的复制机制的Transformers;
- 对于在输出位置t的每个输出token: y(t), CAT的输出概率分布是decoder的生成分布p_gen与复制分布p_copy的混合函数;
- 这个混合函数是被encoder-decoder注意力层通过在原始句子tokens上配置分布来定义的到的;
- 通过在每次deocder的step中定义混合权重参数a_copy(t), 我们定义输出概率如下所示:
+ p(y(t)) = (1-a_copy(t))*p_gen(y(t)) + a_copy(t)*p_copy(y(t))
## 2.3 Denoising Autoencoders (DAEs)
1. DAEs是一类给定噪声版本(noisy version)来学习如何重构原输入的神经网络;
- 给定输入x与一个(随机)噪声函数x-->x~, DAE的encoder-decoder最小化 L(x,dec(enc(x~))), L是某个损失函数;
- 在NLP中, DAEs已经用于可当作降噪任务的seq2seq任务的预训练中;
- 如GEC中, 预训练的DAEs用于修正错误句子;
- 在低资源的MT任务中, 预训练的DAEs用于将word-by-word翻译结果转化为自然语句;
# 3 Related Work (略)
# 4 Pre-training a Denoising Autoencoder on Realistic Grammatical Errors 基于真实语法错误来预训练一个DAE
1. 平行语料太少, 所以我们要做这件事情;
2. 在附属的降噪任务中预训练seq2seq模型时, 噪声函数的选择是很重要的;
- 比如在一个低资源的MT中, 使用噪声函数来随机插入/替代/移除标记或者随机打乱附近单词;
- 这种方法被证明在幼稚(naive)的word-by-word翻译中是有效的, 因为单词——单词的字典的覆盖范围有限, 且单词顺序在不同语言间是经常性的不同的;
3. 一些适合MT生成预训练数据集的噪声函数在GEC中并不很有效:
- 因为单词顺序错误比其他类型的错误(如成分缺失等)要少很多;
- 且随机替换单词这种错误肯定不及指向性的替换(介词错用, 动词时态错误);
4. 因此为了生成真正的预训练数据集, 我们引入一个新颖的噪声函数来捕捉人类常犯的语法错误;
## 4.1 Constructing Noising Scenarios 制定噪声方案
1. 我们引入两种噪声场景(noising scenarios), 使用一个基于标记(token-based)的方法一个基于类别(type-based)的方法;
- token-based方法:
+ 我们利用从标注的GEC语料集中提取出来的人类编辑, 然后使用自动化错误标注工具包, 如ERRANT;
+ 我们首先取训练集的一个子集, 使用错误标注工具包, 收集所有平行语料中的编辑及其频次;
+ 抽出至少发生了k次的编辑, k为一个预设的阈值(我们取k=4), 用于防止在较小的子集上发生过拟合;
+ 这些错误包括一些常见的人类犯的错: 缺少句读, 介词用错, 动词时态用错;
+ 最终我们得到一个训练集上人类标注者制作的常见编辑的自动构建字典;
+ 然后我们可以使用一个真实的噪声方案: 随机采用这些人类的编辑, 应用于语法正确的句子上;
- type-based方法:
+ 我们也使用先验知识(priori knowledge), 创造一个基于token类别的噪声方案: 包括介词, 名词和动词;
+ 对于每种token类别定义一种基于最常犯得错误的噪声方案, 但不会改变原始的token类别: 如换个介词, 名词单复数, 动词不同形式;
+ 这样就得到另外一种真实噪声版本;
## 4.2 Generate Pre-training Data
1. 利用上述噪声方案, 在高质量的英文语料库上(Project Gutenberg corpus, Wikipedia)生成预训练数据;
2. 我们首先检查token是否在token编辑的字典里, 若存在则以0.9的概率生成一个token-based错误(如for替换为during, in, four, 也可以是for, 即noop);
3. 如果不在字典里就根据该token的词性进行第二种噪声处理, 直接替换为同类型另一个单词即可;
# 5 Sequential Transfer Learning 序列迁移学习
## 5.1 Transferring Pre-training DAE Weights 迁移预训练的DAE权重
1. 预训练DAE的一个好处是为在seq2seq模型中为encoder与decoder提供好的初始值权重;
2. 给定预训练好的DAE, 我们使用从DAE中学好的权重初始化seq2seq的GEC模型, 并且在所有可以获得的平行训练语料上训练, 设定的学习率要很小;
3. 这种模型迁移方法可以视为一种(相对简单的)序列迁移学习;
## 5.2 Adaptation by Fine-tuning 微调
1. 不同文本的单词分布是不同的: 如wikipedia中会涉及很多生僻词;
2. 分布会被写者的风格及熟练度影响, 以及标注者的偏好;
3. 本文使用了不同英语熟练度的数据集: W&I+LOCNESS数据集
# 6 A Context-Aware Neural Spellchecker 上下文感知的神经拼写错误检查器
1. 近期许多GEC系统都是用了现成的拼写检查器, 如开源包enchant, 微软Bing拼写检查器;
2. 注意拼写检错还涉及到上下文, 这是近期热点, 如开源包hunspell目前可以在单词级别的程度做到;
- 如: This is an esay about my favourite sport.
- hunspell只能建议esay-->easy, 事实上显然是esay-->essay, 所以上下文很关键;
3. 我们使用的拼写检查器将上下文结合进hunspell, 通过使用一个预训练的神经语言模型(NLM);
4. 特别的, 我们对hunspell推荐的top-candidates进行重排序, 通过将每个候选输入(连同上下文)一起输入给NLM, 然后给它们打分;
# 7 Experiment
1. 我们使用了一个基于PyTorch的seq2seq公开建模工具包: fairseq(0.6.1);
2. 我们还增加了自己实施的复制增强Transformer模型, 包括几个GEC-specific附加损失;
## 7.1 Datasets & Setups 数据集与启动
1. 所有用到的数据集
Source ||| Public? ||| #Sent. ||| #Annot.
Gutenberg ||| Yes ||| 11.6M ||| n/a
Tatoeba ||| Yes ||| 1.17M ||| n/a
WikiText-103 ||| Yes ||| 3.93M ||| n/a
FCE ||| Yes ||| 33.2K ||| 1
Lang-8 ||| Yes ||| 1.04M ||| 1-8
NUCLE ||| Yes ||| 57.2M ||| 1
W&I-Train ||| Yes ||| 34.3K ||| 1
W&I+L-Dev ||| Yes ||| 4.38K ||| 1
W&I+L-Test ||| Yes ||| 4.48K ||| 5
2. Gutenberg, Tatoeba, WikiText-103三个数据集用于预训练, 原因详见P5;
3. 其余所有的数据集用于7.5中Restricted Track;
4. 将W&I+L-Dev分成3:1的训练/测试比例, 用于7.6中Low Resource Track;
## 7.2 Pre-processing 预处理
1. spacy用于tokenize, ERRANT用于evaluate;
2. tokenize后的结果输入到CANS, 我们使用一个在WikiText-103上预训练的gated-CNN语言模型来作为NLM
3. 在拼写检查中, 我们发现改正大小写错误是有效的:
- 我们在WikiText-103中挖掘了一系列单词, 找到里面明显大写比小写出现的多的(>99次);
- 然后把这些单词用于LM重打分过程中;
4. SentencePiece模型: 32K的词汇表(在Gutenberg数据集上训练), 这样在训练集与验证集中避免了<unk>标签;
## 7.3 Model & Training Details 模型与训练细节
1. 实验中使用了两种Transformer: Vanilla Transformer 与 CAT:
- Vanilla Transformer是一个基础模型, 有两种配置:
+ 6-block, 512-2048 units, 8个注意力头;
+ 6-block, 1024-4096 units, 16个注意力头, pre-attention的层标准化;
- CAT:
+ 6-block, 512-4096 units, 8个注意力头, 8头复制注意力层;
- 两个模型分别用两种不同的种子随机训练了两个模型;
2. 模型训练分三步: DAE预训练, 训练, 微调(这一步在Low Resource Task中没有, 因为没有微调数据);
3. 每一步我们训练一个模型直到ERRANT得分收敛, 下降方法为ADAM优化器;
4. 最后的模型是集成不同的模型配置和种子; 在6个最好的模型中
## 7.4 Post-processing 后处理
1. 找到原始输入文本中所有的<unk>标记, 使用ERRANT评估, 我们移除所有与该token相关的编辑;
2. 然后因为许多模型的改正仍然不自然, 如果并非不正确, 我们对候选改正进行重排序(在句内使用一个预训练的NLM);
3. 特别地, 我们移除了改正超过7次的句子, 选择组合使得产生最高的LM得分;
4. 最后我们注意到模型在某些类型的错误表现的好(如PUNCT), 但在其他一些表现得差(如OTHER), 因为ERRANT为模型表现基于错误类型, 提供一个细粒度的(fine-grained)分析, 我们认为去除那些表现的差的错误类型要更好;
## 7.5 Restricted Track Results: 详见Table-3, F0.5=69.06;
## 7.6 Low Resource Track Results: 详见Table-4, F0.5=61.47;
## 7.7 CoNLL-2014 Results: 详见Table-5: M2=60.33
# 8 Analysis & Discussion 分析与讨论
## 8.1 Error Analysis: 详见Table-10, 在一些特定语法错误及其他任务上的表现
## 8.2 Effect of Realistic Error Generation(略)
## 8.3 Effect of Context-Aware Spellchecker(略)
# 9 Conclusion & Future Work 总结与未来工作(略)
----------------------------------------------------
【附录】
# A Copy-Augmented Transformers: Formal Derivation
# B Exploratory Data Analysis
## B.1 Data Sizes
## B.2 Sentence Length vs. Number of Edits
# C Full Noising Algorithm
1. 算法一: 构建噪声字典的伪代码
'''
function CONSTRUCT_NOISE_DICTIONARY(ParallelCorpus, min_count)
Initialize a dictionary dict
for (CorToken, OriToken) in ParallelCorpus do
dict[CorToken] += OriToken
end for
for CorToken, OriTokenList in dict do
for OriToken in OriTokenList do
if count(OriToken)<min_count then
delete OriToken from dict[CorToken]
end if
end for
if length(OriTokenList)==1 and CorToken==OriTokenList[0] then
delete OriToken from dict
end if
end for
return dict
end function
'''
2. 算法二: 生成噪声句子的伪代码: 详见4.1与4.2
'''
function CHANGE_TYPE(word, prob)
preposition set = [Ø, for, to, at, ...]
if random[0, 1] > prob then return word
else
if word in preposition set then
random_choose_one_from(preposition set)
else if word is Noun then change_number(word)
else if word is Verb then change_form(word)
end if
end if
return word
end function
function MAKE_NOISE(sentence, prob)
dict = ConstructNoiseDictionary(ParallelCorpus, min_count)
noised = []
for word in sentence do
if word in dict and random[0, 1]>prob then
candidates = dict[word]
noise = random_choose_one_from(candidates)
else
noise = change_type(word)
end if
noised += noise
end for
return noised
end function
'''
# D Results on error categories: 详见附录中的Table-10
# E CoNLL-2014 Full Results(Without Using W&I+L)
# F Training Details
# G Further Analysis
## G.1 Effect of Copying Mechanisms & Ensembles
以上是关于论文阅读W19-4423——预训练与迁移学习在GEC的应用的主要内容,如果未能解决你的问题,请参考以下文章
论文泛读200通过适配器使用预训练语言模型进行稳健的迁移学习
论文泛读200通过适配器使用预训练语言模型进行稳健的迁移学习
论文泛读117通过中文自然语言推理研究多语言预训练语言模型中的迁移学习
论文泛读171具有对抗性扰动的自监督对比学习,用于鲁棒的预训练语言模型
论文泛读171具有对抗性扰动的自监督对比学习,用于鲁棒的预训练语言模型
自监督论文阅读笔记Integrally Pre-Trained Transformer Pyramid Networks (2022)