BERT的研究与应用可以分为不同的层次。你可以钻研BERT的模型技术细节,了解它为什麽这麽有效,甚至可以发现其中有问题的设计来加以改进,例如RoBERTa就是FB的工程师在BERT之上的改进成果。你也可以去探讨BERT不同层的嵌入之间的差别,来探讨模型如何「学习」到语言文本的知识。
但这些关於BERT的研究都在基础层面,并无法很有效地应用於我们的平常使用中。因为我们和FB、Google的工程师之间有一个巨大差别:缺乏硬体资源,没法重新预训练一个完整的BERT模型。所以,当我们在比赛、作业、研究等情境中使用BERT这类预训练模型时,更关注的是如何在既有的预训练模型基础上更好地应用它们,让它们与Data结合发挥最大效果。
那麽,认识的第一步就是先了解BERT的输入与输出,这时,不妨先将BERT当作一个魔法黑盒子。其中的内部运作我会在接下来几天说明。
词嵌入(Word Embedding)已经在NLP领域中被讨论许久了,而这也是理解BERT的一个很好的切入点。
文字是符号,文本是符号的排列,语义就是被编码进这些符号与符号的排列中。我们认识符号,也能认识符号在不同排列之中的不同意义,是因为我们的大脑对於语言符号会形成一定的「理解」,将其转化为我们脑中可以让神经元计算、沟通的存在形式。但是计算机没有这样的转化系统,计算机只能理解数字,无法辨识符号。
所以词嵌入做的事情就是将文字符号转化为高维度的向量。之所以高维度,是因为语义很复杂,需要较高维度才能充分表现其义。如果你学过特徵抽取,那麽也可以用类似的方式来理解,词嵌入就是对文本序列中的每一个词进行特徵抽取。抽取出来的一串特徵值组成了向量。
在BERT模型发明之前,词嵌入主要由Word2Vec来完成。但Word2Vec的缺点是无法分辨脉络(Context),也就是说,在Word2Vec所转换的词嵌入结果中,一个词在任何语句中的表示向量都是一样的。例如:
大自然真美好,我想生活在绿色环境中。
顺其自然吧,没什麽好难过的。
矿泉水是最自然的饮用品。
三句话中的「自然」的语义都不一样,第一个「自然」指的是自然环境(而且还特指绿色环境),第二个「自然」是指不干预、自由发展,第三个「自然」则是指非人工加工。词本身没有变化,变的是在词语上下的文本脉络。而BERT正可以弥补这个缺失,让词语根据上下文转换成符合脉络的嵌入。因此,BERT的输入必定是一个完整的文本序列。而输出则是序列中每个词语对应的多维向量。以下来详细讨论。
上图是BERT的输入的说明,两道分隔线将图片分成三个部分,最上层是作为文本序列的输入(预处理後的原始资料),第二层是实际BERT模型需要的三个输入,第三层则是在Pytorch、Transformers模组中的三个输入。我们实际用Python进行模型微调的时候只要输入最下方第三层的三个输入即可。
让我们从上往下进行讲解:
可以注意到,文本原文应为「my dog is cute」和「he likes playing」两个句子,但在这边预处理後多了许多被[]包裹着的token。它们别代表的意思是:
除了上述三个之外,BERT还有以下两个特殊token:
BERT模型尚无法读取预处理後的文本,它仍然需要被更进一步转换成BERT所需的格式,也就是三个不同类型的嵌入。你可能会问,词嵌入不是我们的输出吗?怎麽在输入阶段就需要嵌入?别慌,在BERT预训练阶段,这些嵌入是随机初始化并随着模型的训练而得到改善的,在微调阶段,这些嵌入已经被包含在了模型内部的,你不需要实际输入它们。所以你也可以将他们看作模型本身的一部分,知道它们是高维向量即可。
以下我简单做一个说明:
这部分才是我们微调下游任务时实际所需的三个输入。Transformers是目前使用预训练语言模型最流行的一个框架,也是一个python模组,它依赖pytorch。你可以在这里进行更多了解,本系列之後的文章也会介绍。
因为上面已经提到,Token Embeddings、Segment Embeddings、Position Embeddings是已经包含在BERT模型中的嵌入,在实际应用过程中,我们只要能捞取到对应的Embeddings即可,那麽怎麽捞取呢?这些嵌入是以字典的形式进行储存,例如对於Token Embeddings,每一个不同的词(Token)对应固定ID的嵌入。所以我们只要把词语转换为对应的数字id即可。而BERT模型在释出时也会提供相应的字典,让你可以进行自动对应。
这部分的三个输入(下方括号内为此输入在Transformers中的变量名称)分别有:
你可能会好奇,为什麽没有Position Embeddings的对应输入呢?很简单,因为序列的index本身就包含在输入资料内,模型可以替你进行处理。所以虽然Position Embeddings很重要,但是不用自己输入一个[0,1,2,3,4⋯⋯]的序列。而这部分多的masks_tensor则是为了符合实际训练的需要,为了进行Batch运算,同一批次输入的序列长度必须一致,所以需要占位符号,但运算过程中又要排除占位符。、
以上就是BERT模型输入部分的介绍。其实在Transformers中,这个过程可以被简化为如下两行,但了解其背後原理仍是必要的。
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
inputs = tokenizer("my dog is cute","he likes playing")
<<: D5 - 如何用 Google Apps Script 搭配 HTML 客制 Google 表单的回应信件?
JSON serialization/deserialization 应该是不少 Android a...
另一系列悲剧..不小心按到上一页.. 感觉这篇还少了点什麽? 如果平常只用过 Leetcode,建...
Day7 Shoot 是时候帮我们的 LaserCannon 装上子弹了! Input 首先,当玩家...
标题标签** <h1> - <h6> (一级标题 - 六级标题) 文字粗体...
How to Talk to Users: Startup Ideas, Building Prod...