Pre-Training with Whole Word Masking for Chinese BERT

Overview

中文说明 | English



GitHub

在自然语言处理领域中,预训练语言模型(Pre-trained Language Models)已成为非常重要的基础技术。为了进一步促进中文信息处理的研究发展,我们发布了基于全词遮罩(Whole Word Masking)技术的中文预训练模型BERT-wwm,以及与此技术密切相关的模型:BERT-wwm-ext,RoBERTa-wwm-ext,RoBERTa-wwm-ext-large, RBT3, RBTL3。

Pre-Training with Whole Word Masking for Chinese BERT
Yiming Cui, Wanxiang Che, Ting Liu, Bing Qin, Ziqing Yang, Shijin Wang, Guoping Hu

本项目基于谷歌官方BERT:https://github.com/google-research/bert

其他相关资源:

查看更多哈工大讯飞联合实验室(HFL)发布的资源:https://github.com/ymcui/HFL-Anthology

新闻

2021/10/24 哈工大讯飞联合实验室发布面向少数民族语言的预训练模型CINO。查看:https://github.com/ymcui/Chinese-Minority-PLM

2021/7/21 由哈工大SCIR多位学者撰写的《自然语言处理:基于预训练模型的方法》已出版,欢迎大家选购。

2021/1/27 所有模型已支持TensorFlow 2,请通过transformers库进行调用或下载。https://huggingface.co/hfl

2020/9/15 我们的论文"Revisiting Pre-Trained Models for Chinese Natural Language Processing"Findings of EMNLP录用为长文。

2020/8/27 哈工大讯飞联合实验室在通用自然语言理解评测GLUE中荣登榜首,查看GLUE榜单新闻

历史新闻 2020/3/23 本目录发布的模型已接入[飞桨PaddleHub](https://github.com/PaddlePaddle/PaddleHub),查看[快速加载](#快速加载)

2020/3/11 为了更好地了解需求,邀请您填写调查问卷,以便为大家提供更好的资源。

2020/2/26 哈工大讯飞联合实验室发布知识蒸馏工具TextBrewer

2020/1/20 祝大家鼠年大吉,本次发布了RBT3、RBTL3(3层RoBERTa-wwm-ext-base/large),查看小参数量模型

2019/12/19 本目录发布的模型已接入Huggingface-Transformers,查看快速加载

2019/10/14 发布萝卜塔RoBERTa-wwm-ext-large模型,查看中文模型下载

2019/9/10 发布萝卜塔RoBERTa-wwm-ext模型,查看中文模型下载

2019/7/30 提供了在更大通用语料(5.4B词数)上训练的中文BERT-wwm-ext模型,查看中文模型下载

2019/6/20 初始版本,模型已可通过谷歌下载,国内云盘也已上传完毕,查看中文模型下载

内容导引

章节 描述
简介 介绍BERT-wwm基本原理
中文模型下载 提供了BERT-wwm的下载地址
快速加载 介绍了如何使用 🤗 TransformersPaddleHub快速加载模型
模型对比 提供了本目录中模型的参数对比
中文基线系统效果 列举了部分中文基线系统效果
小参数量模型 列举了小参数量模型(3层Transformer)的效果
使用建议 提供了若干使用中文预训练模型的建议
英文模型下载 谷歌官方的英文BERT-wwm下载地址
FAQ 常见问题答疑
引用 本目录的技术报告

简介

Whole Word Masking (wwm),暂翻译为全词Mask整词Mask,是谷歌在2019年5月31日发布的一项BERT的升级版本,主要更改了原预训练阶段的训练样本生成策略。 简单来说,原有基于WordPiece的分词方式会把一个完整的词切分成若干个子词,在生成训练样本时,这些被分开的子词会随机被mask。 在全词Mask中,如果一个完整的词的部分WordPiece子词被mask,则同属该词的其他部分也会被mask,即全词Mask

需要注意的是,这里的mask指的是广义的mask(替换成[MASK];保持原词汇;随机替换成另外一个词),并非只局限于单词替换成[MASK]标签的情况。 更详细的说明及样例请参考:#4

同理,由于谷歌官方发布的BERT-base, Chinese中,中文是以为粒度进行切分,没有考虑到传统NLP中的中文分词(CWS)。 我们将全词Mask的方法应用在了中文中,使用了中文维基百科(包括简体和繁体)进行训练,并且使用了哈工大LTP作为分词工具,即对组成同一个的汉字全部进行Mask。

下述文本展示了全词Mask的生成样例。 注意:为了方便理解,下述例子中只考虑替换成[MASK]标签的情况。

说明 样例
原始文本 使用语言模型来预测下一个词的probability。
分词文本 使用 语言 模型 来 预测 下 一个 词 的 probability 。
原始Mask输入 使 用 语 言 [MASK] 型 来 [MASK] 测 下 一 个 词 的 pro [MASK] ##lity 。
全词Mask输入 使 用 语 言 [MASK] [MASK] 来 [MASK] [MASK] 下 一 个 词 的 [MASK] [MASK] [MASK] 。

中文模型下载

本目录中主要包含base模型,故我们不在模型简称中标注base字样。对于其他大小的模型会标注对应的标记(例如large)。

  • BERT-large模型:24-layer, 1024-hidden, 16-heads, 330M parameters
  • BERT-base模型:12-layer, 768-hidden, 12-heads, 110M parameters
模型简称 语料 Google下载 讯飞云下载
RBT6, Chinese EXT数据[1] - TensorFlow(密码XNMA)
RBT4, Chinese EXT数据[1] - TensorFlow(密码e8dN)
RBTL3, Chinese EXT数据[1] TensorFlow
PyTorch
TensorFlow(密码vySW)
RBT3, Chinese EXT数据[1] TensorFlow
PyTorch
TensorFlow(密码b9nx)
RoBERTa-wwm-ext-large, Chinese EXT数据[1] TensorFlow
PyTorch
TensorFlow(密码u6gC)
RoBERTa-wwm-ext, Chinese EXT数据[1] TensorFlow
PyTorch
TensorFlow(密码Xe1p)
BERT-wwm-ext, Chinese EXT数据[1] TensorFlow
PyTorch
TensorFlow(密码4cMG)
BERT-wwm, Chinese 中文维基 TensorFlow
PyTorch
TensorFlow(密码07Xj)
BERT-base, ChineseGoogle 中文维基 Google Cloud -
BERT-base, Multilingual CasedGoogle 多语种维基 Google Cloud -
BERT-base, Multilingual UncasedGoogle 多语种维基 Google Cloud -

[1] EXT数据包括:中文维基百科,其他百科、新闻、问答等数据,总词数达5.4B。

PyTorch版本

如需PyTorch版本,

1)请自行通过 🤗 Transformers提供的转换脚本进行转换。

2)或者通过huggingface官网直接下载PyTorch版权重:https://huggingface.co/hfl

方法:点击任意需要下载的model → 拉到最下方点击"List all files in model" → 在弹出的小框中下载bin和json文件。

使用说明

中国大陆境内建议使用讯飞云下载点,境外用户建议使用谷歌下载点,base模型文件大小约400M。 以TensorFlow版BERT-wwm, Chinese为例,下载完毕后对zip文件进行解压得到:

chinese_wwm_L-12_H-768_A-12.zip
    |- bert_model.ckpt      # 模型权重
    |- bert_model.meta      # 模型meta信息
    |- bert_model.index     # 模型index信息
    |- bert_config.json     # 模型参数
    |- vocab.txt            # 词表

其中bert_config.jsonvocab.txt与谷歌原版BERT-base, Chinese完全一致。 PyTorch版本则包含pytorch_model.bin, bert_config.json, vocab.txt文件。

快速加载

使用Huggingface-Transformers

依托于Huggingface-Transformers 2.2.2,可轻松调用以上模型。

tokenizer = BertTokenizer.from_pretrained("MODEL_NAME")
model = BertModel.from_pretrained("MODEL_NAME")

注意:本目录中的所有模型均使用BertTokenizer以及BertModel加载,请勿使用RobertaTokenizer/RobertaModel!

其中MODEL_NAME对应列表如下:

模型名 MODEL_NAME
RoBERTa-wwm-ext-large hfl/chinese-roberta-wwm-ext-large
RoBERTa-wwm-ext hfl/chinese-roberta-wwm-ext
BERT-wwm-ext hfl/chinese-bert-wwm-ext
BERT-wwm hfl/chinese-bert-wwm
RBT3 hfl/rbt3
RBTL3 hfl/rbtl3

使用PaddleHub

依托PaddleHub,只需一行代码即可完成模型下载安装,十余行代码即可完成文本分类、序列标注、阅读理解等任务。

import paddlehub as hub
module = hub.Module(name=MODULE_NAME)

其中MODULE_NAME对应列表如下:

模型名 MODULE_NAME
RoBERTa-wwm-ext-large chinese-roberta-wwm-ext-large
RoBERTa-wwm-ext chinese-roberta-wwm-ext
BERT-wwm-ext chinese-bert-wwm-ext
BERT-wwm chinese-bert-wwm
RBT3 rbt3
RBTL3 rbtl3

模型对比

针对大家比较关心的一些模型细节进行汇总如下。

- BERTGoogle BERT-wwm BERT-wwm-ext RoBERTa-wwm-ext RoBERTa-wwm-ext-large
Masking WordPiece WWM[1] WWM WWM WWM
Type base base base base large
Data Source wiki wiki wiki+ext[2] wiki+ext wiki+ext
Training Tokens # 0.4B 0.4B 5.4B 5.4B 5.4B
Device TPU Pod v2 TPU v3 TPU v3 TPU v3 TPU Pod v3-32[3]
Training Steps ? 100KMAX128
+100KMAX512
1MMAX128
+400KMAX512
1MMAX512 2MMAX512
Batch Size ? 2,560 / 384 2,560 / 384 384 512
Optimizer AdamW LAMB LAMB AdamW AdamW
Vocabulary 21,128 ~BERT[4] ~BERT ~BERT ~BERT
Init Checkpoint Random Init ~BERT ~BERT ~BERT Random Init

[1] WWM = Whole Word Masking
[2] ext = extended data
[3] TPU Pod v3-32 (512G HBM)等价于4个TPU v3 (128G HBM)
[4] ~BERT表示继承谷歌原版中文BERT的属性

中文基线系统效果

为了对比基线效果,我们在以下几个中文数据集上进行了测试,包括句子级篇章级任务。 对于BERT-wwm-extRoBERTa-wwm-extRoBERTa-wwm-ext-large,我们没有进一步调整最佳学习率,而是直接使用了BERT-wwm的最佳学习率。

最佳学习率:

模型 BERT ERNIE BERT-wwm*
CMRC 2018 3e-5 8e-5 3e-5
DRCD 3e-5 8e-5 3e-5
CJRC 4e-5 8e-5 4e-5
XNLI 3e-5 5e-5 3e-5
ChnSentiCorp 2e-5 5e-5 2e-5
LCQMC 2e-5 3e-5 2e-5
BQ Corpus 3e-5 5e-5 3e-5
THUCNews 2e-5 5e-5 2e-5

*代表所有wwm系列模型 (BERT-wwm, BERT-wwm-ext, RoBERTa-wwm-ext, RoBERTa-wwm-ext-large)

下面仅列举部分结果,完整结果请查看我们的技术报告

注意:为了保证结果的可靠性,对于同一模型,我们运行10遍(不同随机种子),汇报模型性能的最大值和平均值(括号内为平均值)。不出意外,你运行的结果应该很大概率落在这个区间内。

评测指标中,括号内表示平均值,括号外表示最大值。

简体中文阅读理解:CMRC 2018

CMRC 2018数据集是哈工大讯飞联合实验室发布的中文机器阅读理解数据。 根据给定问题,系统需要从篇章中抽取出片段作为答案,形式与SQuAD相同。 评测指标为:EM / F1

模型 开发集 测试集 挑战集
BERT 65.5 (64.4) / 84.5 (84.0) 70.0 (68.7) / 87.0 (86.3) 18.6 (17.0) / 43.3 (41.3)
ERNIE 65.4 (64.3) / 84.7 (84.2) 69.4 (68.2) / 86.6 (86.1) 19.6 (17.0) / 44.3 (42.8)
BERT-wwm 66.3 (65.0) / 85.6 (84.7) 70.5 (69.1) / 87.4 (86.7) 21.0 (19.3) / 47.0 (43.9)
BERT-wwm-ext 67.1 (65.6) / 85.7 (85.0) 71.4 (70.0) / 87.7 (87.0) 24.0 (20.0) / 47.3 (44.6)
RoBERTa-wwm-ext 67.4 (66.5) / 87.2 (86.5) 72.6 (71.4) / 89.4 (88.8) 26.2 (24.6) / 51.0 (49.1)
RoBERTa-wwm-ext-large 68.5 (67.6) / 88.4 (87.9) 74.2 (72.4) / 90.6 (90.0) 31.5 (30.1) / 60.1 (57.5)

繁体中文阅读理解:DRCD

DRCD数据集由中国台湾台达研究院发布,其形式与SQuAD相同,是基于繁体中文的抽取式阅读理解数据集。 由于ERNIE中去除了繁体中文字符,故不建议在繁体中文数据上使用ERNIE(或转换成简体中文后再处理)。 评测指标为:EM / F1

模型 开发集 测试集
BERT 83.1 (82.7) / 89.9 (89.6) 82.2 (81.6) / 89.2 (88.8)
ERNIE 73.2 (73.0) / 83.9 (83.8) 71.9 (71.4) / 82.5 (82.3)
BERT-wwm 84.3 (83.4) / 90.5 (90.2) 82.8 (81.8) / 89.7 (89.0)
BERT-wwm-ext 85.0 (84.5) / 91.2 (90.9) 83.6 (83.0) / 90.4 (89.9)
RoBERTa-wwm-ext 86.6 (85.9) / 92.5 (92.2) 85.6 (85.2) / 92.0 (91.7)
RoBERTa-wwm-ext-large 89.6 (89.1) / 94.8 (94.4) 89.6 (88.9) / 94.5 (94.1)

司法阅读理解:CJRC

CJRC数据集是哈工大讯飞联合实验室发布的面向司法领域的中文机器阅读理解数据。 需要注意的是实验中使用的数据并非官方发布的最终数据,结果仅供参考。 评测指标为:EM / F1

模型 开发集 测试集
BERT 54.6 (54.0) / 75.4 (74.5) 55.1 (54.1) / 75.2 (74.3)
ERNIE 54.3 (53.9) / 75.3 (74.6) 55.0 (53.9) / 75.0 (73.9)
BERT-wwm 54.7 (54.0) / 75.2 (74.8) 55.1 (54.1) / 75.4 (74.4)
BERT-wwm-ext 55.6 (54.8) / 76.0 (75.3) 55.6 (54.9) / 75.8 (75.0)
RoBERTa-wwm-ext 58.7 (57.6) / 79.1 (78.3) 59.0 (57.8) / 79.0 (78.0)
RoBERTa-wwm-ext-large 62.1 (61.1) / 82.4 (81.6) 62.4 (61.4) / 82.2 (81.0)

自然语言推断:XNLI

在自然语言推断任务中,我们采用了XNLI数据,需要将文本分成三个类别:entailmentneutralcontradictory。 评测指标为:Accuracy

模型 开发集 测试集
BERT 77.8 (77.4) 77.8 (77.5)
ERNIE 79.7 (79.4) 78.6 (78.2)
BERT-wwm 79.0 (78.4) 78.2 (78.0)
BERT-wwm-ext 79.4 (78.6) 78.7 (78.3)
RoBERTa-wwm-ext 80.0 (79.2) 78.8 (78.3)
RoBERTa-wwm-ext-large 82.1 (81.3) 81.2 (80.6)

情感分析:ChnSentiCorp

在情感分析任务中,二分类的情感分类数据集ChnSentiCorp。 评测指标为:Accuracy

模型 开发集 测试集
BERT 94.7 (94.3) 95.0 (94.7)
ERNIE 95.4 (94.8) 95.4 (95.3)
BERT-wwm 95.1 (94.5) 95.4 (95.0)
BERT-wwm-ext 95.4 (94.6) 95.3 (94.7)
RoBERTa-wwm-ext 95.0 (94.6) 95.6 (94.8)
RoBERTa-wwm-ext-large 95.8 (94.9) 95.8 (94.9)

句对分类:LCQMC, BQ Corpus

以下两个数据集均需要将一个句对进行分类,判断两个句子的语义是否相同(二分类任务)。

LCQMC

LCQMC由哈工大深圳研究生院智能计算研究中心发布。 评测指标为:Accuracy

模型 开发集 测试集
BERT 89.4 (88.4) 86.9 (86.4)
ERNIE 89.8 (89.6) 87.2 (87.0)
BERT-wwm 89.4 (89.2) 87.0 (86.8)
BERT-wwm-ext 89.6 (89.2) 87.1 (86.6)
RoBERTa-wwm-ext 89.0 (88.7) 86.4 (86.1)
RoBERTa-wwm-ext-large 90.4 (90.0) 87.0 (86.8)

BQ Corpus

BQ Corpus由哈工大深圳研究生院智能计算研究中心发布,是面向银行领域的数据集。 评测指标为:Accuracy

模型 开发集 测试集
BERT 86.0 (85.5) 84.8 (84.6)
ERNIE 86.3 (85.5) 85.0 (84.6)
BERT-wwm 86.1 (85.6) 85.2 (84.9)
BERT-wwm-ext 86.4 (85.5) 85.3 (84.8)
RoBERTa-wwm-ext 86.0 (85.4) 85.0 (84.6)
RoBERTa-wwm-ext-large 86.3 (85.7) 85.8 (84.9)

篇章级文本分类:THUCNews

篇章级文本分类任务我们选用了由清华大学自然语言处理实验室发布的新闻数据集THUCNews。 我们采用的是其中一个子集,需要将新闻分成10个类别中的一个。 评测指标为:Accuracy

模型 开发集 测试集
BERT 97.7 (97.4) 97.8 (97.6)
ERNIE 97.6 (97.3) 97.5 (97.3)
BERT-wwm 98.0 (97.6) 97.8 (97.6)
BERT-wwm-ext 97.7 (97.5) 97.7 (97.5)
RoBERTa-wwm-ext 98.3 (97.9) 97.7 (97.5)
RoBERTa-wwm-ext-large 98.3 (97.7) 97.8 (97.6)

小参数量模型

以下是在若干NLP任务上的实验效果,表中只提供测试集结果对比。

模型 CMRC 2018 DRCD XNLI CSC LCQMC BQ 平均 参数量
RoBERTa-wwm-ext-large 74.2 / 90.6 89.6 / 94.5 81.2 95.8 87.0 85.8 87.335 325M
RoBERTa-wwm-ext 72.6 / 89.4 85.6 / 92.0 78.8 95.6 86.4 85.0 85.675 102M
RBTL3 63.3 / 83.4 77.2 / 85.6 74.0 94.2 85.1 83.6 80.800 61M (59.8%)
RBT3 62.2 / 81.8 75.0 / 83.9 72.3 92.8 85.1 83.3 79.550 38M (37.3%)

效果相对值比较:

模型 CMRC 2018 DRCD XNLI CSC LCQMC BQ 平均 分类平均
RoBERTa-wwm-ext-large 102.2% / 101.3% 104.7% / 102.7% 103.0% 100.2% 100.7% 100.9% 101.9% 101.2%
RoBERTa-wwm-ext 100% / 100% 100% / 100% 100% 100% 100% 100% 100% 100%
RBTL3 87.2% / 93.3% 90.2% / 93.0% 93.9% 98.5% 98.5% 98.4% 94.3% 97.35%
RBT3 85.7% / 91.5% 87.6% / 91.2% 91.8% 97.1% 98.5% 98.0% 92.9% 96.35%
  • 参数量是以XNLI分类任务为基准进行计算
  • 括号内参数量百分比以原始base模型(即RoBERTa-wwm-ext)为基准
  • RBT3:由RoBERTa-wwm-ext 3层进行初始化,继续训练了1M步
  • RBTL3:由RoBERTa-wwm-ext-large 3层进行初始化,继续训练了1M步
  • RBT的名字是RoBERTa三个音节首字母组成,L代表large模型
  • 直接使用RoBERTa-wwm-ext-large前三层进行初始化并进行下游任务的训练将显著降低效果,例如在CMRC 2018上测试集仅能达到42.9/65.3,而RBTL3能达到63.3/83.4

使用建议

  • 初始学习率是非常重要的一个参数(不论是BERT还是其他模型),需要根据目标任务进行调整。
  • ERNIE的最佳学习率和BERT/BERT-wwm相差较大,所以使用ERNIE时请务必调整学习率(基于以上实验结果,ERNIE需要的初始学习率较高)。
  • 由于BERT/BERT-wwm使用了维基百科数据进行训练,故它们对正式文本建模较好;而ERNIE使用了额外的百度贴吧、知道等网络数据,它对非正式文本(例如微博等)建模有优势。
  • 在长文本建模任务上,例如阅读理解、文档分类,BERTBERT-wwm的效果较好。
  • 如果目标任务的数据和预训练模型的领域相差较大,请在自己的数据集上进一步做预训练。
  • 如果要处理繁体中文数据,请使用BERT或者BERT-wwm。因为我们发现ERNIE的词表中几乎没有繁体中文。

英文模型下载

为了方便大家下载,顺便带上谷歌官方发布的英文BERT-large (wwm)模型:

FAQ

Q: 这个模型怎么用?
A: 谷歌发布的中文BERT怎么用,这个就怎么用。 文本不需要经过分词,wwm只影响预训练过程,不影响下游任务的输入。

Q: 请问有预训练代码提供吗?
A: 很遗憾,我不能提供相关代码,实现可以参考 #10#13

Q: 某某数据集在哪里下载?
A: 请查看data目录,任务目录下的README.md标明了数据来源。对于有版权的内容,请自行搜索或与原作者联系获取数据。

Q: 会有计划发布更大模型吗?比如BERT-large-wwm版本?
A: 如果我们从实验中得到更好效果,会考虑发布更大的版本。

Q: 你骗人!无法复现结果 😂
A: 在下游任务中,我们采用了最简单的模型。比如分类任务,我们直接使用的是run_classifier.py(谷歌提供)。 如果无法达到平均值,说明实验本身存在bug,请仔细排查。 最高值存在很多随机因素,我们无法保证能够达到最高值。 另外一个公认的因素:降低batch size会显著降低实验效果,具体可参考BERT,XLNet目录的相关Issue。

Q: 我训出来比你更好的结果!
A: 恭喜你。

Q: 训练花了多长时间,在什么设备上训练的?
A: 训练是在谷歌TPU v3版本(128G HBM)完成的,训练BERT-wwm花费约1.5天,BERT-wwm-ext则需要数周时间(使用了更多数据需要迭代更充分)。 需要注意的是,预训练阶段我们使用的是LAMB OptimizerTensorFlow版本实现)。该优化器对大的batch有良好的支持。 在微调下游任务时,我们采用的是BERT默认的AdamWeightDecayOptimizer

Q: ERNIE是谁?
A: 本项目中的ERNIE模型特指百度公司提出的ERNIE,而非清华大学在ACL 2019上发表的ERNIE

Q: BERT-wwm的效果不是在所有任务都很好
A: 本项目的目的是为研究者提供多元化的预训练模型,自由选择BERT,ERNIE,或者是BERT-wwm。 我们仅提供实验数据,具体效果如何还是得在自己的任务中不断尝试才能得出结论。 多一个模型,多一种选择。

Q: 为什么有些数据集上没有试?
A: 很坦率的说: 1)没精力找更多的数据; 2)没有必要; 3)没有钞票;

Q: 简单评价一下这几个模型
A: 各有侧重,各有千秋。 中文自然语言处理的研究发展需要多方共同努力。

Q: 你预测下一个预训练模型叫什么?
A: 可能叫ZOE吧,ZOE: Zero-shOt Embeddings from language model

Q: 更多关于RoBERTa-wwm-ext模型的细节?
A: 我们集成了RoBERTa和BERT-wwm的优点,对两者进行了一个自然的结合。 和之前本目录中的模型之间的区别如下:
1)预训练阶段采用wwm策略进行mask(但没有使用dynamic masking)
2)简单取消Next Sentence Prediction(NSP)loss
3)不再采用先max_len=128然后再max_len=512的训练模式,直接训练max_len=512
4)训练步数适当延长

需要注意的是,该模型并非原版RoBERTa模型,只是按照类似RoBERTa训练方式训练出的BERT模型,即RoBERTa-like BERT。 故在下游任务使用、模型转换时请按BERT的方式处理,而非RoBERTa。

引用

如果本目录中的内容对你的研究工作有所帮助,欢迎在论文中引用下述论文。

@journal{cui-etal-2021-pretrain,
  title={Pre-Training with Whole Word Masking for Chinese BERT},
  author={Cui, Yiming and Che, Wanxiang and Liu, Ting and Qin, Bing and Yang, Ziqing},
  journal={IEEE Transactions on Audio, Speech and Language Processing},
  year={2021},
  url={https://ieeexplore.ieee.org/document/9599397},
  doi={10.1109/TASLP.2021.3124365},
 }
@inproceedings{cui-etal-2020-revisiting,
    title = "Revisiting Pre-Trained Models for {C}hinese Natural Language Processing",
    author = "Cui, Yiming  and
      Che, Wanxiang  and
      Liu, Ting  and
      Qin, Bing  and
      Wang, Shijin  and
      Hu, Guoping",
    booktitle = "Proceedings of the 2020 Conference on Empirical Methods in Natural Language Processing: Findings",
    month = nov,
    year = "2020",
    address = "Online",
    publisher = "Association for Computational Linguistics",
    url = "https://www.aclweb.org/anthology/2020.findings-emnlp.58",
    pages = "657--668",
}

致谢

第一作者部分受到谷歌TensorFlow Research Cloud计划资助。

免责声明

本项目并非谷歌官方发布的Chinese BERT-wwm模型。同时,本项目不是哈工大或科大讯飞的官方产品。 技术报告中所呈现的实验结果仅表明在特定数据集和超参组合下的表现,并不能代表各个模型的本质。 实验结果可能因随机数种子,计算设备而发生改变。 该项目中的内容仅供技术研究参考,不作为任何结论性依据。使用者可以在许可证范围内任意使用该模型,但我们不对因使用该项目内容造成的直接或间接损失负责。

关注我们

欢迎关注哈工大讯飞联合实验室官方微信公众号,了解最新的技术动态。

qrcode.png

问题反馈

如有问题,请在GitHub Issue中提交。

Comments
  • TensorFlow版本的AdamWeightDecayOptimizer在fine-tune BERT时不起作用,请问您有遇到过吗?

    TensorFlow版本的AdamWeightDecayOptimizer在fine-tune BERT时不起作用,请问您有遇到过吗?

    """Functions and classes related to optimization (weight updates)."""
    
    from __future__ import absolute_import
    from __future__ import division
    from __future__ import print_function
    
    import re
    import tensorflow as tf
    from tensorflow.python.framework import ops
    from tensorflow.python.ops import control_flow_ops
    from tensorflow.python.ops import math_ops
    from tensorflow.python.training import optimizer
    from tensorflow.python.ops import state_ops
    from tensorflow.python.ops import resource_variable_ops
    
    
    def create_optimizer(loss, init_lr, num_train_steps, num_warmup_steps, use_tpu):
        """Creates an optimizer training op."""
        global_step = tf.train.get_or_create_global_step()
    
        learning_rate = tf.constant(value=init_lr, shape=[], dtype=tf.float32)
    
        # Implements linear decay of the learning rate.
        learning_rate = tf.train.polynomial_decay(
            learning_rate,
            global_step,
            num_train_steps,
            end_learning_rate=0.0,
            power=1.0,
            cycle=False)
    
        # Implements linear warmup. I.e., if global_step < num_warmup_steps, the
        # learning rate will be `global_step/num_warmup_steps * init_lr`.
        if num_warmup_steps:
            global_steps_int = tf.cast(global_step, tf.int32)
            warmup_steps_int = tf.constant(num_warmup_steps, dtype=tf.int32)
    
            global_steps_float = tf.cast(global_steps_int, tf.float32)
            warmup_steps_float = tf.cast(warmup_steps_int, tf.float32)
    
            warmup_percent_done = global_steps_float / warmup_steps_float
            warmup_learning_rate = init_lr * warmup_percent_done
    
            is_warmup = tf.cast(global_steps_int < warmup_steps_int, tf.float32)
            learning_rate = (
                    (1.0 - is_warmup) * learning_rate + is_warmup * warmup_learning_rate)
    
        # It is recommended that you use this optimizer for fine tuning, since this
        # is how the model was trained (note that the Adam m/v variables are NOT
        # loaded from init_checkpoint.)
        optimizer = AdamWeightDecayOptimizer(
            learning_rate=learning_rate,
            weight_decay_rate=0.01,
            beta_1=0.9,
            beta_2=0.999,
            epsilon=1e-6,
            exclude_from_weight_decay=["LayerNorm", "layer_norm", "bias"])
    
        if use_tpu:
            optimizer = tf.contrib.tpu.CrossShardOptimizer(optimizer)
    
        tvars = tf.trainable_variables()
        grads = tf.gradients(loss, tvars)
    
        # This is how the model was pre-trained.
        (grads, _) = tf.clip_by_global_norm(grads, clip_norm=1.0)
    
        train_op = optimizer.apply_gradients(
            zip(grads, tvars), global_step=global_step)
    
        # Normally the global step update is done inside of `apply_gradients`.
        # However, `AdamWeightDecayOptimizer` doesn't do this. But if you use
        # a different optimizer, you should probably take this line out.
        new_global_step = global_step + 1
        train_op = tf.group(train_op, [global_step.assign(new_global_step)])
        return train_op
    
    class AdamWeightDecayOptimizer(optimizer.Optimizer):
        """A basic Adam optimizer that includes "correct" L2 weight decay."""
    
        def __init__(self,
                     learning_rate,
                     weight_decay_rate=0.0,
                     beta_1=0.9,
                     beta_2=0.999,
                     epsilon=1e-6,
                     exclude_from_weight_decay=None,
                     name="AdamWeightDecayOptimizer"):
            """Constructs a AdamWeightDecayOptimizer."""
            super(AdamWeightDecayOptimizer, self).__init__(False, name)
    
            self.learning_rate = learning_rate
            self.weight_decay_rate = weight_decay_rate
            self.beta_1 = beta_1
            self.beta_2 = beta_2
            self.epsilon = epsilon
            self.exclude_from_weight_decay = exclude_from_weight_decay
    
        def _prepare(self):
            self.learning_rate_t = ops.convert_to_tensor(
                self.learning_rate, name='learning_rate')
            self.weight_decay_rate_t = ops.convert_to_tensor(
                self.weight_decay_rate, name='weight_decay_rate')
            self.beta_1_t = ops.convert_to_tensor(self.beta_1, name='beta_1')
            self.beta_2_t = ops.convert_to_tensor(self.beta_2, name='beta_2')
            self.epsilon_t = ops.convert_to_tensor(self.epsilon, name='epsilon')
    
        def _create_slots(self, var_list):
            for v in var_list:
                self._zeros_slot(v, 'm', self._name)
                self._zeros_slot(v, 'v', self._name)
    
        def _apply_dense(self, grad, var):
            learning_rate_t = math_ops.cast(
                self.learning_rate_t, var.dtype.base_dtype)
            beta_1_t = math_ops.cast(self.beta_1_t, var.dtype.base_dtype)
            beta_2_t = math_ops.cast(self.beta_2_t, var.dtype.base_dtype)
            epsilon_t = math_ops.cast(self.epsilon_t, var.dtype.base_dtype)
            weight_decay_rate_t = math_ops.cast(
                self.weight_decay_rate_t, var.dtype.base_dtype)
    
            m = self.get_slot(var, 'm')
            v = self.get_slot(var, 'v')
    
            # Standard Adam update.
            next_m = (
                tf.multiply(beta_1_t, m) +
                tf.multiply(1.0 - beta_1_t, grad))
            next_v = (
                tf.multiply(beta_2_t, v) + tf.multiply(1.0 - beta_2_t,
                                                       tf.square(grad)))
    
            update = next_m / (tf.sqrt(next_v) + epsilon_t)
    
            if self._do_use_weight_decay(var.name):
                update += weight_decay_rate_t * var
    
            update_with_lr = learning_rate_t * update
    
            next_param = var - update_with_lr
    
            return control_flow_ops.group(*[var.assign(next_param),
                                            m.assign(next_m),
                                            v.assign(next_v)])
    
        def _resource_apply_dense(self, grad, var):
            learning_rate_t = math_ops.cast(
                self.learning_rate_t, var.dtype.base_dtype)
            beta_1_t = math_ops.cast(self.beta_1_t, var.dtype.base_dtype)
            beta_2_t = math_ops.cast(self.beta_2_t, var.dtype.base_dtype)
            epsilon_t = math_ops.cast(self.epsilon_t, var.dtype.base_dtype)
            weight_decay_rate_t = math_ops.cast(
                self.weight_decay_rate_t, var.dtype.base_dtype)
    
            m = self.get_slot(var, 'm')
            v = self.get_slot(var, 'v')
    
            # Standard Adam update.
            next_m = (
                tf.multiply(beta_1_t, m) +
                tf.multiply(1.0 - beta_1_t, grad))
            next_v = (
                tf.multiply(beta_2_t, v) + tf.multiply(1.0 - beta_2_t,
                                                       tf.square(grad)))
    
            update = next_m / (tf.sqrt(next_v) + epsilon_t)
    
            if self._do_use_weight_decay(var.name):
                update += weight_decay_rate_t * var
    
            update_with_lr = learning_rate_t * update
    
            next_param = var - update_with_lr
    
            return control_flow_ops.group(*[var.assign(next_param),
                                            m.assign(next_m),
                                            v.assign(next_v)])
    
        def _apply_sparse_shared(self, grad, var, indices, scatter_add):
            learning_rate_t = math_ops.cast(
                self.learning_rate_t, var.dtype.base_dtype)
            beta_1_t = math_ops.cast(self.beta_1_t, var.dtype.base_dtype)
            beta_2_t = math_ops.cast(self.beta_2_t, var.dtype.base_dtype)
            epsilon_t = math_ops.cast(self.epsilon_t, var.dtype.base_dtype)
            weight_decay_rate_t = math_ops.cast(
                self.weight_decay_rate_t, var.dtype.base_dtype)
    
            m = self.get_slot(var, 'm')
            v = self.get_slot(var, 'v')
    
            m_t = state_ops.assign(m, m * beta_1_t,
                                   use_locking=self._use_locking)
    
            m_scaled_g_values = grad * (1 - beta_1_t)
            with ops.control_dependencies([m_t]):
                m_t = scatter_add(m, indices, m_scaled_g_values)
    
            v_scaled_g_values = (grad * grad) * (1 - beta_2_t)
            v_t = state_ops.assign(v, v * beta_2_t, use_locking=self._use_locking)
            with ops.control_dependencies([v_t]):
                v_t = scatter_add(v, indices, v_scaled_g_values)
    
            update = m_t / (math_ops.sqrt(v_t) + epsilon_t)
    
            if self._do_use_weight_decay(var.name):
                update += weight_decay_rate_t * var
    
            update_with_lr = learning_rate_t * update
    
            var_update = state_ops.assign_sub(var,
                                              update_with_lr,
                                              use_locking=self._use_locking)
            return control_flow_ops.group(*[var_update, m_t, v_t])
    
        def _apply_sparse(self, grad, var):
            return self._apply_sparse_shared(
                grad.values, var, grad.indices,
                lambda x, i, v: state_ops.scatter_add(  # pylint: disable=g-long-lambda
                    x, i, v, use_locking=self._use_locking))
    
        def _resource_scatter_add(self, x, i, v):
            with ops.control_dependencies(
                [resource_variable_ops.resource_scatter_add(
                    x.handle, i, v)]):
                return x.value()
    
        def _resource_apply_sparse(self, grad, var, indices):
            return self._apply_sparse_shared(
                grad, var, indices, self._resource_scatter_add)
    
        def _do_use_weight_decay(self, param_name):
            """Whether to use L2 weight decay for `param_name`."""
            if not self.weight_decay_rate:
                return False
            if self.exclude_from_weight_decay:
                for r in self.exclude_from_weight_decay:
                    if re.search(r, param_name) is not None:
                        return False
            return True
    

    @ymcui 多谢多谢多谢!

    opened by guotong1988 15
  • Chinese-BERT-wwm对于Masked LM 任务(完形填空,ERNIE中提到的那种),表现怎么样?有测试过么?

    Chinese-BERT-wwm对于Masked LM 任务(完形填空,ERNIE中提到的那种),表现怎么样?有测试过么?

    Chinese-BERT-wwm对于Masked LM 任务(完形填空,ERNIE中提到的那种),表现怎么样?有测试过么? 另外WWM采取了新的Mask策略,如果我想在此基础上增加一些专业领域词汇做pre-training,该怎么做?BERT原声模型中有相应的代码,但是因为两个模型mask策略不同,应该不能直接用原生BERT模型,能不能开源一下修改后的模型呢?

    opened by Finley1991 14
  • ner评估是用的那个值

    ner评估是用的那个值

    seqeval的评估值有micro avg和 macro avg,报告里写的是那个值? precision recall f1-score support

       MISC       0.00      0.00      0.00         1
        PER       1.00      1.00      1.00         1
    

    micro avg 0.50 0.50 0.50 2 macro avg 0.50 0.50 0.50 2

    opened by ak47-1234 11
  • 相同配置代码,重复运行结果不同?

    相同配置代码,重复运行结果不同?

    你好,我们的BERT-wwm-ext(tf)模型做ner和情感分类任务,在相同的配置也指定了随机种子的情况下,两次运行结果不同,换了google的BERT或roBERTa都不会出现这个问题。用部分样本训练发现,样本不多(20条)时结果是一样的,但训练样本大以后,结果就不同了。不知道什么原因,谢谢你的解答。

    stale 
    opened by sirlb 9
  • wwm训练的模型,如何使用bert的tokenize?

    wwm训练的模型,如何使用bert的tokenize?

    您好,我有几个问题,想咨询一下: 1、中文使用WWM预训练时,会将"公司" tokenize 为 [“公”,"##司"],mask时,会将"公司"mask为“[[MASK],[MASK]]”,请问此时label是["公","司"]还是["公","##司"]? 2、如果label使用的是["公","##司"]来训练的话,那么训练的就是“##司”,而不是“司”;那么在后续模型的使用时,使用bert的BertTokenizer,只会将"公司"tokenize为[“公”,"司"],但是按照WWM的思想,应该要tokenize 为 [“公”,"##司"]。“##司”和“司”二者的embeddings是不一样的。后续模型的使用,是不是也需要分词? 麻烦帮忙解答一下!!!谢谢

    opened by nathinal 9
  • 我想问下全词mask的一个小细节

    我想问下全词mask的一个小细节

    在你们的工作中,比如mask词的时候,一个词为哈利波特,那么在你们的方法中,是不是只要这个词被mask,那一定是[mask][mask][mask][mask]的形式,还是偶尔会出现[mask]利[mask][mask]的形式,不知道你们是如何设置的(不考虑那个mask80%10%10%的那个随机概率),如果是前者,那么这种完全避免局部共现的设置会不会对结果有影响。

    opened by fudanchenjiahao 9
  • NotImplementedError

    NotImplementedError

    您好,请问加载TFBertModel时出现 NotImplementedError: Weights may only be loaded based on topology into Models when loading TensorFlow-formatted weights (got by_name=True to load_weights)报错是什么原因导致的呢?

    stale 
    opened by lzl19971215 8
  • ValueError: Couldn't find 'checkpoint' file or checkpoints in given directory chinese_roberta_wwm_ext_L-12_H-768_A-12

    ValueError: Couldn't find 'checkpoint' file or checkpoints in given directory chinese_roberta_wwm_ext_L-12_H-768_A-12

    ValueError: Couldn't find 'checkpoint' file or checkpoints in given directory chinese_roberta_wwm_ext_L-12_H-768_A-12

    尝试用 https://github.com/huggingface/pytorch-transformers/blob/master/pytorch_transformers/convert_tf_checkpoint_to_pytorch.py 这个代码convert roberta的checkpoint,报了这个错,请问是为什么呢?

    opened by fyubang 8
  • 阅读理解在实现上是不是有问题

    阅读理解在实现上是不是有问题

    把Bert、和Bert-wwm的模型转成paddle, 基于 https://github.com/PaddlePaddle/LARK/tree/develop/BERT 的代码在DRCD数据集上finetune,配置跟论文一致,评估脚本:https://github.com/ymcui/CMRC2018-DRCD-BERT/blob/master/cmrc2018_evaluate.py 。效果如下(十次平均): image

    复现的结果普遍比论文结果高2~3个点,是不是论文实现的阅读理解有问题?

    opened by zhanghan1992 8
  • 关于不能用RobertaModel引用

    关于不能用RobertaModel引用

    您好,在readme中的快速加载有这样一句:

    注意:本目录中的所有模型均使用BertTokenizer以及BertModel加载,请勿使用RobertaTokenizer/RobertaModel!

    我从huggingface官网下下来了roberta-chinese-wwm的pytorch_model.bin,tokenizer.json和vocab,再想在代码使用.from_pretrained()方法引用,即不是采用快速加载的情况,请问这样的话是用RobertaModel引用还是BertModel引用呢?我尝试用BertModel引用,但是提示:

    You are using a model of type roberta to instantiate a model of type bert. This is not supported for all configurations of models and can yield errors.`

    还请解答一下,非常感谢!

    stale 
    opened by Jackthebighead 7
  • transformer 实现 WWM 来 Fine-tune Bert 相关问题

    transformer 实现 WWM 来 Fine-tune Bert 相关问题

    您好,非常感谢您这边的工作。 我最近在 transformers 中实现了 WWM 的 Fine-tune,相关 PR 已经被 merge 到 master 分支, 具体可以参见:这里

    具体的实现参考了 #13 中的描述:对于BERT 的分词结果,使用 LTP 的分词结果,对特定位置的索引添加 ##,后面 mask 部分代码就可以直接套用 Google 代码。

    有两个细节上的小问题,希望您不吝解答:

    1. LTP 的分词结果是否是动态的 ?因为我看是分词结果是有隐层向量输出的,而不是像 Jieba 一样是基于词表。
    2. 如果想要 Fine-tune,对数据的清洗应该做到什么程度,或者是否可以提供一下参考的文献?
    stale 
    opened by wlhgtc 7
Owner
Yiming Cui
NLP Researcher. Mainly interested in Machine Reading Comprehension, Question Answering, Pre-trained Language Model, etc.
Yiming Cui
Beyond Masking: Demystifying Token-Based Pre-Training for Vision Transformers

beyond masking Beyond Masking: Demystifying Token-Based Pre-Training for Vision Transformers The code is coming Figure 1: Pipeline of token-based pre-

Yunjie Tian 23 Sep 27, 2022
天池中药说明书实体识别挑战冠军方案;中文命名实体识别;NER; BERT-CRF & BERT-SPAN & BERT-MRC;Pytorch

天池中药说明书实体识别挑战冠军方案;中文命名实体识别;NER; BERT-CRF & BERT-SPAN & BERT-MRC;Pytorch

zxx飞翔的鱼 751 Dec 30, 2022
A collection of Classical Chinese natural language processing models, including Classical Chinese related models and resources on the Internet.

GuwenModels: 古文自然语言处理模型合集, 收录互联网上的古文相关模型及资源. A collection of Classical Chinese natural language processing models, including Classical Chinese related models and resources on the Internet.

Ethan 66 Dec 26, 2022
Chinese real time voice cloning (VC) and Chinese text to speech (TTS).

Chinese real time voice cloning (VC) and Chinese text to speech (TTS). 好用的中文语音克隆兼中文语音合成系统,包含语音编码器、语音合成器、声码器和可视化模块。

Kuang Dada 6 Nov 8, 2022
vits chinese, tts chinese, tts mandarin

vits chinese, tts chinese, tts mandarin 史上训练最简单,音质最好的语音合成系统

AmorTX 12 Dec 14, 2022
pkuseg多领域中文分词工具; The pkuseg toolkit for multi-domain Chinese word segmentation

pkuseg:一个多领域中文分词工具包 (English Version) pkuseg 是基于论文[Luo et. al, 2019]的工具包。其简单易用,支持细分领域分词,有效提升了分词准确度。 目录 主要亮点 编译和安装 各类分词工具包的性能对比 使用方式 论文引用 作者 常见问题及解答 主要

LancoPKU 6k Dec 29, 2022
100+ Chinese Word Vectors 上百种预训练中文词向量

Chinese Word Vectors 中文词向量 中文 This project provides 100+ Chinese Word Vectors (embeddings) trained with different representations (dense and sparse),

embedding 10.4k Jan 9, 2023
Pre-training BERT masked language models with custom vocabulary

Pre-training BERT Masked Language Models (MLM) This repository contains the method to pre-train a BERT model using custom vocabulary. It was used to p

Stella Douka 14 Nov 2, 2022
TaCL: Improve BERT Pre-training with Token-aware Contrastive Learning

TaCL: Improve BERT Pre-training with Token-aware Contrastive Learning

Yixuan Su 26 Oct 17, 2022
iBOT: Image BERT Pre-Training with Online Tokenizer

Image BERT Pre-Training with iBOT Official PyTorch implementation and pretrained models for paper iBOT: Image BERT Pre-Training with Online Tokenizer.

Bytedance Inc. 435 Jan 6, 2023
Chinese NER with albert/electra or other bert descendable model (keras)

Chinese NLP (albert/electra with Keras) Named Entity Recognization Project Structure ./ ├── NER │   ├── __init__.py │   ├── log

null 2 Nov 20, 2022
Chinese named entity recognization (bert/roberta/macbert/bert_wwm with Keras)

Chinese named entity recognization (bert/roberta/macbert/bert_wwm with Keras)

null 2 Jul 5, 2022
Chinese Pre-Trained Language Models (CPM-LM) Version-I

CPM-Generate 为了促进中文自然语言处理研究的发展,本项目提供了 CPM-LM (2.6B) 模型的文本生成代码,可用于文本生成的本地测试,并以此为基础进一步研究零次学习/少次学习等场景。[项目首页] [模型下载] [技术报告] 若您想使用CPM-1进行推理,我们建议使用高效推理工具BMI

Tsinghua AI 1.4k Jan 3, 2023
LV-BERT: Exploiting Layer Variety for BERT (Findings of ACL 2021)

LV-BERT Introduction In this repo, we introduce LV-BERT by exploiting layer variety for BERT. For detailed description and experimental results, pleas

Weihao Yu 14 Aug 24, 2022
VD-BERT: A Unified Vision and Dialog Transformer with BERT

VD-BERT: A Unified Vision and Dialog Transformer with BERT PyTorch Code for the following paper at EMNLP2020: Title: VD-BERT: A Unified Vision and Dia

Salesforce 44 Nov 1, 2022
Pytorch-version BERT-flow: One can apply BERT-flow to any PLM within Pytorch framework.

Pytorch-version BERT-flow: One can apply BERT-flow to any PLM within Pytorch framework.

Ubiquitous Knowledge Processing Lab 59 Dec 1, 2022
Universal End2End Training Platform, including pre-training, classification tasks, machine translation, and etc.

背景 安装教程 快速上手 (一)预训练模型 (二)机器翻译 (三)文本分类 TenTrans 进阶 1. 多语言机器翻译 2. 跨语言预训练 背景 TrenTrans是一个统一的端到端的多语言多任务预训练平台,支持多种预训练方式,以及序列生成和自然语言理解任务。 安装教程 git clone git

Tencent Minority-Mandarin Translation Team 42 Dec 20, 2022