一大批中文(BERT等)预训练模型等你认领!
项目简介
预训练模型已经成为了 NLP 领域最重要的资源之一。当我们拿到一个 NLP 数据集时,首要任务是寻找一个预训练模型。当然,目前大家会趋同的选择 Google 发布的 BERT 模型 [1]。
不过本文将为大家提供更多的中文预训练模型的选择!本文将介绍如何利用一个预训练模型框架 UER(Universal Encoder Representations)去使用性质各异的中文预训练模型,从而在下游任务上取得比 Google BERT 更好的效果。
预训练模型一般分成四个部分:语料、编码器、目标任务以及微调策略。已有的工作从这四个部分中选择不同的模块(比如选择不同的目标任务),构成一个预训练模型(如下图所示)[1,2,3]。
图1. 预训练模型和它们使用的模块。BERT模型使用12层Transformer编码器,遮罩语言模型+下一句子预测作为目标任务,并将整个模型迁移到下游任务进行微调
语料、编码器、目标任务对于一个预训练模型的性质有着重要的影响。虽然目前 Google BERT 模型一枝独秀,但是 Google BERT 选择的语料、编码器、目标任务对于很多的下游任务数据集未必是合适的(Google BERT 使用中文维基百科语料+12 层 Transformer 编码器+遮罩语言模型任务&句子预测任务)。
因此,我们这里提供了一个基于不同语料、不同编码器以及不同目标任务的中文预训练模型仓库(model zoo)。UER 的代码和模型仓库可以在这里获取:
https://github.com/dbiir/UER-py
用户在模型仓库中选择适合下游任务的预训练模型进行下载并在上面微调。话不多说,下面我们一起看看如何用 UER 和它的模型仓库为我们的下游任务带来 SOTA 的效果!
快速上手
我们首先以非常火的 BERT 模型 [1] 和豆瓣书评情感分类数据集 [6] 为例,看看 UER 配合着模型仓库如何带来更好的预训练模型使用体验(更好的表现&更高的效率)。我们以使用者的角度,来上手操作一番。
我们首先要下载预训练模型。第一个下载的是 Google 官方的预训练模型(github 项目包含了所有预训练模型的下载地址)。我们把下载好的预训练模型放到 models 文件夹中。然后我们执行如下命令:
这里简单介绍一下各个选项的意义:--pretrained_model_path 指定预训练模型的路径;--vocab_path 指定词典的路径;下游任务数据集路径通过 --train_path、--dev_path、--test_path 指定;--encoder 指定我们使用的编码器,这里使用 BERT 中的 12 层 Transformer 编码器。
通过在 Google BERT 模型上微调,这里得到了 87.01 的结果。这个结果和 UER 项目中给的 87.5 的准确率有差距。如果更改 seed 的话结果会有一定的波动。UER 项目给的结果是多次取平均得到的。
下面,我们尝试其它的预训练模型,期待获得更好的效果。这里首先通过在一个小规模书评语料上预训练来得到一个更适合书评分类数据集的预训练模型。
我们加载 Google BERT 预训练模型,然后在小规模书评语料上进行无监督的预训练。本文侧重微调阶段,即如何在下游任务上利用好模型仓库中的预训练模型。至于预训练方面的细节,本文不加赘述。
UER 项目已经为我们提供了在小规模书评语料上预训练好的模型。我们直接下载下来,放到 models 文件夹之中。下面进行分类任务。和前面执行 Google BERT 的命令相比,现在只需要替换预训练模型的路径(--pretrained_model_path):
通过在 book_review_model.bin 上进行微调,我们得到了 88.05 的结果,相对于 BERT 提升比较显著。
上面的模型只是在小规模语料上训练的结果。我们可以从 UER 的模型仓库中去搜索更加合适的预训练模型。Amazon_cls_model.bin 使用分类目标任务和 Amazon 评论语料 [10] 进行预训练。由于这个模型的语料和书评语料性质接近,并利用了有监督信息 [3],所以这份预训练模型可能对于书评数据集是一个很好的选择。
实验结果显示,通过加载 amazon_cls_model.bin,我们得到了 88.65 的准确率。虽然 BERT 的效果已经非常厉害了,超出了之前的模型一大截距离,但是我们在 BERT 的基础上仍然获得了显著的提升!
BERT 模型非常强大,但是效率较低,这严重限制了 BERT 的使用场景。比如当我们使用 BERT 进行前向 inference 的时候,普通 CPU 一秒钟只能处理两三条。这在很多的场景中是不能接受的。因此,UER 还提供了一些基于轻量级编码器的预训练模型,以期实现更为快速的训练过程,同时能够兼顾准确率。
这里仍然使用上面的豆瓣书评数据集对模型进行评估。我们在模型仓库中选择一个基于 2 层 LSTM 编码器的预训练模型,lstm_reveiews_model.bin。这个模型首先在大规模混合语料上用语言模型(LM)作为目标任务进行预训练,然后再在 Amazon 带标签的评论语料 [10] 上用语言模型(LM)和分类(CLS)目标任务进行预训练。我们将这个预训练模型用于豆瓣书评数据集上:
这里需要手动指定配置路径--config_path,因为 classifier.py 默认使用的是 BERT 的配置。通过微调,我们得到了 86.68 的准确率。如果不加载预训练模型(随机初始化),LSTM 仅仅能得到 80.25 的准确率。由此可以看到预训练模型的重要性。
下面我们将 LSTM 编码器用于 ChnSentiCorp 情感分类数据集。我们只需要将命令行中的 train_path、dev_path、test_path 更改为相应路径即可。
我们使用 LSTM 编码器得到了 94.5 的准确率。可以看到使用合适的基于轻量级编码器的预训练模型可以在这两个分类任务上得到非常有竞争力的结果。在实验中,使用 2 层 LSTM 编码器的预训练模型比 BERT 快了 10 倍。
可以看到,在模型仓库中选择合适的预训练模型用于情感分类任务,真的做到了又快又好!虽然编码器的能力不如 BERT 的 12 层 transformer,但是得益于对语料和目标任务合理的选择,我们仍然得到了比肩 BERT 的效果。期待轻量级的编码器能在更多的下游任务上有好的表现!
最后我们使用 UER 进行了序列标注任务,数据集为 MSRA-NER。这里有两个实验。第一个用 Google 提供的 BERT 预训练模型做序列标注,第二个用 UER 提供的在人民日报上使用 BERT 进行预训练的模型。
由于 MSRA-NER 数据集是在新闻语料上进行的序列标注,选择基于人民日报的预训练模型是比较合适的选择。下面是序列标注的脚本,我们分别使用 google_model.bin 和 rmrb_model.bin 作为预训练模型:
最后实验结果显示使用人民日报模型的效果比 Google BERT 要好不少,相对于百度的 ERNIE 预训练模型也有一定的优势 [4]。通过上面几个例子,可以看到在很多情况下,Google BERT 并非是最合适的预训练模型。通过在 UER 模型仓库中选择合适的预训练模型,可以帮助我们在下游任务得到更好的表现。
我们在知乎上对 UER 的使用进行了连载:
里面记录了我们使用 UER 遇到的各种情形和细节问题(包括预训练和下游任务微调)。如果想立马使用 UER 去得到有竞争力的结果,可以移步到我们的连载中去。
模型仓库
上面我们介绍了如何使用 UER 去调用各种中文预训练模型,这里进一步对这个项目提供的模型仓库进行介绍。首先,这么多中文预训练模型都是怎么得到的呢?事实上,模型仓库中的预训练模型均是由 UER 训练得到的。这里对 UER 进行一个简要的介绍。
UER 使用了解耦的设计框架。它的子编码器、编码器、目标任务之间有着清晰的接口,可以帮助我们对不同模块进行轻松的组合。这个项目也实现了不少的模块,为我们提供了丰富的示例。UER 的整体结构如下图所示:
从图 2 的上半部分可以看到,UER 实现了多个目标任务模块、编码器模块以及子编码器模块。UER-py 目前实现了以下目标任务:
lm_target.py:语言模型
mlm_target.py:遮罩语言模型(完形填空测试)
nsp_target.py:下一句话预测
cls_target.py:分类
s2s_target.py:seq2seq,支持自编码器和机器翻译作为预训练目标任务
bert_target.py:遮罩语言模型+下一句话预测以及实现了以下编码器:以及实现了以下编码器:
以及实现了以下编码器:
rnn_encoder.py:包含(双向)LSTM 和(双向)GRU
cnn_encoder.py:包含 CNN 和 GatedCNN
attn_encoder.py:包含注意力神经网络编码器
gpt_encoder.py:包含 GPT 编码器
bert_encoder.py:包含 BERT 编码器
mixed_encoder.py:包含基本编码器的组合,例如 RCNN(RNN + CNN),CRNN(CNN + RNN)
子编码器负责在字的特征上抽取信息得到词的特征。子编码器在预训练模型上用得不多,一个使用子编码器的经典的工作是 ELMO。得益于 UER 这种解耦的设计,我们可以轻松地使用不同的编码器、目标任务的组合,训练出不同性质的预训练模型。
因此,UER 的模型仓库提供了基于不同语料、编码器、以及目标任务的预训练模型。UER 项目给出了每一个预训练模型的细节,比如在什么语料上训练了多少步(参见 UER 项目中的 readme)。
图 3 给出了我们已有的语料、编码器、目标任务的组合。图 4 给出了项目中预训练模型下载链接和描述的截图。
此外,UER 项目还给出了在大规模数据集上训练的模型。这些数据集来自于 GLYPH:
https://github.com/zhangxiangxiao/glyph
这些大规模数据集属于新闻主题分类和情感分析任务,每个数据集包括了从几十万到上百万的训练样本。得到的预训练模型能帮助我们直接验证 BERT 在几个大数据集上的效果。此外,这些预训练模型还可以继续用于其它下游任务数据集,相信将它们用于新闻、评论相关的任务会对结果有着显著的提升。
未来工作
1. 发布的预训练模型并没有使用遮词策略。百度的 ERNIE [4] 和哈工大&讯飞 [5] 最近的工作都显示了遮词对于预训练模型的重要性。分词信息对于中文 NLP 确实很重要,我们后续会发布引入多种改进策略的预训练模型,包括遮词策略、多任务学习等等。
对于将分词信息引入 BERT 这个思路,我们在之前也训练了基于词的 BERT 模型,并在以词搜词上取得了非常不错的效果,大家可以关注这个工作。
2. 我们一下子给出了接近二十个预训练模型。或许用训练这二十个模型的计算力,训练一个超级模型会更好?我们之前在做词向量的时候,发现大规模混合的语料带来的收益非常之高,因此,后面我们希望后面集中力量在大语料上训练一个大模型,并加入多种改进机制。
这里推荐下载该项目下的在 mixed-large 语料上使用 character 和 ngram 特征训练的词向量:
https://github.com/Embedding/Chinese-Word-Vectors
当然,这一批预训练模型还是很有意义的。通过前面的实验也看到,在不同任务上选择合适的预训练模型能帮助我们取得 SOTA 的结果。到底是训练一个超集模型,还是训练一批性质各异,满足不同下游任务的预训练模型?这仍然是一个开放的问题。
结束语
本文介绍了用 UER 训练的一批中文预训练模型,并展示了通过对这些预训练模型进行合理的利用,可以取得非常有竞争力的表现(更好的效果,更高的效率)。当我们再面对一个数据集的时候,我们的预训练模型选择不再局限于 Google BERT(或者百度的 ERNIE [4],哈工大&讯飞的 BERT-wwm [5])。
UER 模型仓库中的预训练模型各有特点,适用于不同的场景。我们希望大家能够关注我们的工作,听到大家想要的预训练模型,也希望这个工作对中文 NLP 领域能起到一点帮助。
参考资料
[1] Devlin J, Chang M W, Lee K, et al. Bert: Pre-training of deep bidirectional transformers for language understanding[J]. arXiv preprint arXiv:1810.04805, 2018.
[2] Radford A, Narasimhan K, Salimans T, et al. Improving language understanding by generative pre-training[J]. 2018.
[3] Conneau A, Kiela D, Schwenk H, et al. Supervised learning of universal sentence representations from natural language inference data[J]. arXiv preprint arXiv:1705.02364, 2017.
[4] https://github.com/PaddlePaddle/LARK/tree/develop/ERNIE
[5] https://github.com/ymcui/Chinese-BERT-wwm
[6] Qiu Y, Li H, Li S, et al. Revisiting Correlations between Intrinsic and Extrinsic Evaluations of Word Embeddings[M]//Chinese Computational Linguistics and Natural Language Processing Based on Naturally Annotated Big Data. Springer, Cham, 2018: 209-221.
[7] Liu X, Chen Q, Deng C, et al. LCQMC: A Large-scale Chinese Question Matching Corpus[C]//Proceedings of the 27th International Conference on Computational Linguistics. 2018: 1952-1962.
[8] http://tcci.ccf.org.cn/conference/2016/dldoc/evagline2.pdf
[9] https://github.com/facebookresearch/XNLI
[10] https://github.com/SophonPlus/ChineseNlpCorpus
[11] https://github.com/brightmart/nlp_chinese_corpus