动机、参考资料、涉及内容

动机

  • Google 原版 bert 代码学习

参考资料

涉及内容

  • 尽量用自然语言描述代码,只附上相应的源码链接

模型结构

Bert 也做了 emdedding 和输出层预测 token 做了 tie-weight

预训练

数据处理

原始文本的格式如下,具体例子可参考源代码库样例文件

总体处理逻辑为:

  • 句子 -> 预处理 -> 转化为 token
  • 文章 -> 每个句子都 token 化 -> 训练样本

tokenize的过程中, 经过各种预处理后, 最终每个句子变成 word 序列

# unicode 字符:U+0B90: ஐ, name 为 TAMIL LETTER AI
["apples", "dஐapp", "er"]
# 假设词表为[apple, ##es, er, ##s, er, d, ##app, app]

# 转换为的 token 序列为: 每个词用贪心算法查找词典: 先看apples在不在词表里, 再看apple在不在词表里
# 特殊情况1: 对于dஐapp, 在编码了d后, 一直查找词典都没找到, 则把整个ஐapp当作<unk>
# 特殊情况2: 如果某个词的长度超过了200, 则把整个词当作<unk>
=> [apple, ##s, d, <unk>, er]

每个example都有两段话, 部分被mask掉了, 需要同时预测mask掉的部分以及两段话是否出自同一篇文章

一个具体的example例子为(这里是对源码的准确理解, 对于完全复现, 具有参考意义):

# 假设设定模型的序列长度为16, 最多的mask数量为6个
paragraph_a, paragraph_b = "AB CD EF", "G HI J K"
# 原始实现里: 85%为"O"操作, 剩下的15%为替换操作, 其中: "M" 为 80%, "R" 为 10%, "RO" 为 10%
# ops表示对原始数据的操作: "O" 表示不操作, "M" 表示替换为 [MASK], "R" 表示替换为另一个, "RO" 表示替换为本身, 等同于"O" 
ops =        ["O"    , "O", "M"  , "O", "O"  , "M"  , "R"  , "O"    , "O", "O", "M"  , "RO", "O", "O"  ] + ["O", "O"]
range_helper=[0      ,  1 ,  2   ,  3 ,  4   ,  5   ,  6   ,  7     ,  8 ,  9 , 10   ,  11 , 12 , 13   ] + [14, 15]
ori_tokens = ["[CLS]", "A", "##B", "C", "##D", "E"  , "##F", "[SEP]", "G", "H", "##I", "J" , "K", "SEP"] + [0,  0]

# 以下为实际存储的数据(为了直观, token_id用token表示了)
input_ids =  ["[CLS]", "A", "[M]", "C", "##D", "[M]", "A",   "[SEP]", "G", "H", "[M]", "J" , "K", "SEP"] + [0, 0]
input_mask = [1      , 1  , 1    , 1  , 1    , 1    , 1    , 1      , 1  , 1  , 1    , 1   , 1  , 1    ] + [0, 0]
segment_ids= [0      , 0  , 0    , 0  , 0    , 0    , 0    , 0      , 1  , 1  , 1    , 1   , 1  , 1    ] + [0, 0]

masked_lm_positions = [2    , 5  , 6    , 10   , 11] + [0]  # 发生修改的位置, 补齐到 6
masked_lm_ids =       ["##B", "E", "##F", "##I", "J"] + [0] # 发生修改位置的真实标签, 及ori_tokens中相应位置的值
masked_lm_weights   = [1.0  , 1.0, 1.0  , 1.0  , 1.0] + [0.0]
next_sentence_labels = 1  # 如果前后两端话是相连的, 取值为1, 否则取值为 0.

说明:

  • 第 2、10 个位置的操作不是 WWM(Whole Word Mask),而第 5、6个位置的操作是 WWM,并且对于 WWM,每个 wordpiece 的具体操作可以不一样:这个例子中第 5 个位置的操作是替换为 MASK,第 6 个位置是替换为其他字符

fine-tune 训练

原始代码仓库中的 fine-tune 采用的是不冻结参数

其他资料

BERT 官方仓库中并未提供 BERT 预训练所使用的 BooksCorpus (800M words) 和 English Wikipedia (2500M words) 这两个数据集的下载方式。

🤗 Transfomers 官方文档 推荐了这篇博客“复现” BERT的训练过程。其中提到了以上两个数据集已在 🤗 Datasets 维护:BooksCorpusEnglish Wikipedia

备注:BERT原始论文中的 English Wikipedia 与 🤗 Datasets 上维护的版本有差异