在研究变换器模型时,我们往往关注模型的架构以及用于训练它们的数据集。我们已经探索了原始的Transformer,微调了类似BERT的模型,训练了一个RoBERTa模型,探索了一个GPT-3模型,训练了一个GPT-2模型,实施了一个T5模型等。我们还研究了主要的基准任务和数据集。
我们训练了一个RoBERTa分词器并使用分词器对数据进行编码。然而,我们没有探索分词器的极限,以评估它们与我们构建的模型的匹配程度。人工智能是数据驱动的。Raffel等人(2019),就像本书中引用的所有作者一样,花了时间为变换器模型准备数据集。
在本章中,我们将讨论一些限制分词器质量的分词器限制。不要轻信预训练的分词器。您可能有自己使用的特定词汇表(例如高级医学术语),其中包含通用预训练分词器未处理的单词。
我们将首先介绍一些与分词器无关的最佳实践,以衡量分词器的质量。我们将从分词的角度描述数据集和分词器的基本指南。
然后,我们将使用Word2Vec分词器来展示分词方法所面临的问题。这些限制将通过Python程序进行说明。
我们将继续我们的研究,对包含特定词汇的数据集运行一个GPT-2模型,包括无条件和有条件的样本。
我们将深入探讨字节级BPE方法的限制。我们将构建一个Python程序,显示由GPT-2分词器生成的结果,并探讨数据编码过程中出现的问题。这将展示,对于常见的自然语言处理分析,GPT-3的卓越性并不总是必要的。
然而,在本章的最后,我们将使用一个词性(POS)任务来测试GPT-3引擎,以查看模型理解的程度,以及现成的分词字典是否适合我们的需求。
本章涵盖以下主题:
- 控制分词器输出的基本指南
- 原始数据策略和数据预处理策略
- Word2Vec分词问题和限制
- 创建一个Python程序来评估Word2Vec分词器
- 构建一个Python程序来评估字节级BPE算法的输出
- 使用特定词汇自定义自然语言处理任务
- 在GPT-2上运行无条件和有条件的样本
- 评估GPT-2分词器
我们的第一步将是探索Raffel等人(2019)定义的文本到文本方法论。
匹配数据集和分词器
下载基准数据集以训练变换器具有许多优势。数据已经准备好,并且每个研究实验室都使用相同的参考资料。此外,可以将变换器模型的性能与使用相同数据的其他模型进行比较。
然而,我们需要做更多工作来提高变换器的性能。此外,在生产中实施变换器模型需要谨慎规划和定义最佳实践。
在本节中,我们将定义一些最佳实践,以避免关键的障碍。
然后,我们将通过使用余弦相似性在Python中的一些示例来衡量分词和编码数据集的限制。
让我们从最佳实践开始。
最佳实践
Raffel等人(2019)定义了一个标准的文本到文本T5变换器模型。他们还进一步前进。他们开始打破了使用未经预处理的原始数据的神话。
预处理数据可以减少训练时间。例如,Common Crawl包含通过Web抓取获取的无标签文本。非文本内容和标记已从数据集中删除。
然而,Google T5团队发现,通过Common Crawl获取的文本很多并未达到自然语言或英语的水平。因此,他们决定在使用数据集之前对其进行清理。
我们将采纳Raffel等人(2019)提出的建议,并将公司的质量控制最佳实践应用于预处理和质量控制阶段。除了要应用的许多其他规则之外,所述示例展示了获得可接受的实际项目数据集所需的大量工作。
图9.1列出了适用于数据集的一些关键质量控制流程:
如图9.1所示,质量控制分为两个阶段:在训练变换器时的预处理阶段(步骤1)以及在变换器投入生产时的质量控制阶段(步骤2)。
让我们详细了解一下预处理阶段的一些主要方面。
步骤1:预处理
Raffel等人(2019)建议在对数据集进行模型训练之前进行预处理,我添加了一些额外的想法。
变换器已经成为语言学习者,而我们成为了它们的教师。但要教会机器学生一门语言,我们必须解释什么是正确的英语,例如。
在使用数据集之前,我们需要对其应用一些标准的启发式方法:
- 包含标点符号的句子 推荐选择以标点符号结尾的句子,如句号或问号。
- 删除不良词汇 应该删除不良词汇。例如,可以在以下网站上找到列表:github.com/LDNOOBW/Lis…
- 删除代码 这有点棘手,因为有时代码就是我们要查找的内容。然而,通常最好从自然语言处理任务的内容中删除代码。
- 语言检测 有时,网站包含带有默认“lorem ipsum”文本的页面。必须确保数据集的所有内容都是我们所希望的语言。一个很好的开始方式是使用langdetect,它可以检测50多种语言:pypi.org/project/lan…
- 删除歧视性引用 这是必须的。我的建议是建立一个知识库,汇集您可以从网上或从特定数据集中获取的所有内容。消除任何形式的歧视。毫无疑问,您希望您的机器具备道德。
- 逻辑检查 可以尝试在执行自然语言推理(NLI)的数据集上运行经过训练的变换器模型,以筛选那些毫无意义的句子。
- 不良信息引用 删除指向不起作用的链接、不道德的网站或个人的文本。这是一项艰巨的工作,但绝对是值得的。
这个列表包含了一些主要的最佳实践。然而,还需要更多的工作,比如过滤侵犯隐私法律的内容和针对特定项目的其他操作。
一旦变换器被训练成了解正确的英语,我们需要在生产阶段帮助它检测输入文本中的问题。
第二步:质量控制
训练好的模型将表现得像一个学会语言的人。它将理解它所能理解的内容并从输入数据中学习。输入数据应经历与第1步:预处理相同的过程,并向训练数据集添加新信息。而训练数据集,反过来,可以成为公司项目中的知识库。用户将能够在数据集上运行自然语言处理任务,获取可靠的答案、特定文档的有用摘要等。
我们应该将第1步:预处理中描述的最佳实践应用到实时输入数据中。例如,一个变换器可以在用户输入或自然语言处理任务(如总结文档列表)上运行。
变换器是迄今为止最强大的自然语言处理模型。这意味着我们的伦理责任也更加重要。
让我们看一些最佳实践:
- 实时检查输入文本 不要接受不良信息。相反,在实时解析输入并过滤不可接受的数据(参见第1步)。
- 实时消息 将被过滤的数据以及过滤原因存储起来,以便用户可以查看日志。如果变换器被要求回答不合适的问题,显示实时消息。
- 语言转换 在可能的情况下,可以将罕见的词汇转换为标准词汇。参见本章中Word2Vec分词化部分的Case 4。这并非总是可能的。但在可能的情况下,它可能代表一步向前。
- 隐私检查 无论是将数据流式传输到变换器模型还是分析用户输入,私人数据必须在未经用户或变换器所运行国家授权的情况下从数据集和任务中排除。这是一个棘手的问题。在必要时请咨询法律顾问。
我们刚刚介绍了一些最佳实践。现在让我们看一下为什么需要人工质量控制。
持续的人工质量控制
变换器将逐渐接管大多数复杂的自然语言处理任务。然而,人类干预仍然是必要的。我们以为社交媒体巨头已经实现了自动化的一切。然后我们发现有内容管理员决定了什么对他们的平台是好的或坏的。
正确的方法是训练一个变换器,实施它,控制输出,并将重要的结果反馈到训练集中。因此,训练集将不断改进,变换器将继续学习。
图9.2显示了持续的质量控制如何帮助变换器的训练数据集增长,并提高其在生产中的性能:
我们已经介绍了Raffel等人(2019)描述的一些最佳实践,并我基于我在企业人工智能项目管理方面的经验添加了一些建议。
让我们看一下一个Python程序,其中包括一些示例,演示了使用分词器时遇到的一些限制。
Word2Vec分词化
只要事情顺利,没有人会考虑预训练的分词器。这就像现实生活中一样。我们可以多年开车而不去考虑引擎的问题。然后,有一天,我们的车抛锚了,我们试图找出原因来解释这种情况。
同样,对于预训练分词器也是如此。有时结果并不如我们所期望的那样。例如,有些词对在一起并不合适,正如我们在图9.3中所看到的那样:
图9.3中的示例来自美国独立宣言、权利法案和英格兰大宪章:
- “cake” 和 “chapters” 不适合放在一起,尽管一个分词器计算它们具有很高的余弦相似性值。
- “freedom” 指的是言论自由,例如。”copyright” 指的是自由电子书的编辑所写的注释。
- “pay” 和 “bill” 在日常英语中是合适的。多义性是指一个词可以有多个含义。例如,”Bill” 意味着要支付的金额,但也指的是权利法案。结果是可以接受的,但可能只是纯粹的运气。
在继续之前,让我们澄清一些要点。QC指的是质量控制。在任何战略性企业项目中,QC都是必不可少的。输出的质量将决定关键项目的生存。如果项目不是战略性的,有时错误可能是可以接受的。在战略项目中,即使有一些错误,也会涉及风险管理审计,以查看项目是否应该继续或放弃。
从质量控制和风险管理的角度来看,对于与问题无关的数据集(包含太多无用的词或缺少关键词)进行分词化将混淆嵌入算法并产生“差结果”。这就是为什么在本章中,我宽泛地使用了“分词化”这个词,因为一个会影响另一个。
在战略人工智能项目中,”差结果” 可能会导致一个错误,产生严重后果(特别是在医疗领域、飞机或火箭装配或其他关键领域)。
打开Tokenizer.ipynb,它基于第2章中创建的positional_encoding.ipynb,开始了Transformer模型的架构入门。
由于Word2Vec算法的随机性质,结果可能会因一次运行与另一次运行而有所不同。
首先安装和导入了所需的先决条件:
#@title Pre-Requisistes
!pip install gensim==3.8.3
import nltk
nltk.download('punkt')
import math
import numpy as np
from nltk.tokenize import sent_tokenize, word_tokenize
import gensim
from gensim.models import Word2Vec
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings(action = 'ignore')
text.txt,我们的数据集,包含了美国独立宣言、权利法案、大宪章、伊曼纽尔·康德的著作以及其他文本。
现在,我们将对text.txt进行分词处理并训练一个Word2Vec模型:
#@title Word2Vec Tokenization
#'text.txt' file
sample = open("text.txt", "r")
s = sample.read()
# processing escape characters
f = s.replace("n", " ")
data = []
# sentence parsing
for i in sent_tokenize(f):
temp = []
# tokenize the sentence into words
for j in word_tokenize(i):
temp.append(j.lower())
data.append(temp)
# Creating Skip Gram model
model2 = gensim.models.Word2Vec(data, min_count = 1, size = 512,window = 5, sg = 1)
print(model2)
window = 5 是一个有趣的参数。它限制了输入句子中当前单词和预测单词之间的距离。sg = 1 表示使用了skip-gram训练算法。
输出显示词汇表的大小为10816,嵌入的维度为512,学习速率设置为 alpha=0.025:
Word2Vec(vocab=10816, size=512, alpha=0.025)
我们有一个包含嵌入的词表示模型,并可以创建一个名为 similarity(word1, word2)
的余弦相似度函数。我们将将 word1
和 word2
发送到该函数,它将返回它们之间的余弦相似度值。值越高,相似度越高。
该函数将首先检测到未知词 [unk]
,并显示一条消息:
#@title Cosine Similarity
def similarity(word1,word2):
cosine=False #default value
try:
a=model2[word1]
cosine=True
except KeyError: #The KeyError exception is raised
print(word1, ":[unk] key not found in dictionary")#False implied
try:
b=model2[word2]#a=True implied
except KeyError: #The KeyError exception is raised
cosine=False #both a and b must be true
print(word2, ":[unk] key not found in dictionary")
只有当 cosine==True
时,余弦相似度才会被计算,这意味着 word1
和 word2
都是已知的:
if(cosine==True):
b=model2[word2]
# compute cosine similarity
dot = np.dot(a, b)
norma = np.linalg.norm(a)
normb = np.linalg.norm(b)
cos = dot / (norma * normb)
aa = a.reshape(1,512)
ba = b.reshape(1,512)
#print("Word1",aa)
#print("Word2",ba)
cos_lib = cosine_similarity(aa, ba)
#print(cos_lib,"word similarity")
if(cosine==False):cos_lib=0;
return cos_lib
该函数将返回 cos_lib
,即计算得到的余弦相似度值。
现在,我们将讨论六种情况。我们将称text.txt为“数据集”。
让我们从第0种情况开始。
情况0:数据集中的单词和词典中的单词
数据集中包含单词 “freedom” 和 “liberty”,它们的余弦相似度可以计算:
#@title Case 0: Words in text and dictionary
word1="freedom";word2="liberty"
print("Similarity",similarity(word1,word2),word1,word2)
相似度受到了限制,为0.79,因为从各种文本中插入了大量内容来探索该函数的限制:
Similarity [[0.79085565]] freedom liberty
相似度算法不是一个迭代的确定性计算。本节的结果可能会随着数据集内容、另一次运行后数据集大小或模块版本的变化而变化。如果您多次运行该单元格,您可能会或可能不会获得不同的值,就像在以下10次运行中一样。
在以下情况下,我在Google Colab VM和CPU上连续10次获得了相同的结果:
Run 1: Similarity [[0.62018466]] freedom liberty
Run 2: Similarity [[0.62018466]] freedom liberty
...
Run 10: Similarity [[0.62018466]] freedom liberty
然而,我在Google Colab的运行时菜单中执行了“工厂重置运行时”。使用新的虚拟机和CPU,我获得了以下结果:
Run 1: Similarity [[0.51549244]] freedom liberty
Run 2: Similarity [[0.51549244]] freedom liberty
...
Run 10: Similarity [[0.51549244]] freedom liberty
我执行了Google Colab运行时菜单中的另一次“factory reset runtime”。我还启用了GPU。使用新的虚拟机和GPU,我获得了以下结果:
Run 1: Similarity [[0.58365834]] freedom liberty
Run 2: Similarity [[0.58365834]] freedom liberty
...
Run 10: Similarity [[0.58365834]] freedom liberty
这里的结论是,随机算法基于概率。如果需要的话,多次运行预测是一个好的实践。
现在让我们看看当一个单词缺失时会发生什么。
情况1:不在数据集或词典中的单词
缺失的单词在许多方面都会带来麻烦。在这种情况下,我们将”corporations”和”rights”发送到相似度函数中。
#@title Word(s) Case 1: Word not in text or dictionary
word1="corporations";word2="rights"
print("Similarity",similarity(word1,word2),word1,word2)
词典中不包含单词 “corporations”:
corporations :[unk] key not found in dictionary
Similarity 0 corporations rights
缺失的单词会在许多方面引发问题。在这种情况下,我们将 corporations 和 rights 发送到相似度函数中。
缺失的单词会引发一系列事件和问题,如果这个单词很重要,会扭曲变换器模型的输出。我们将缺失的单词称为 unk。
需要检查并回答几种可能性:
- unk 在数据集中,但未被选定为分词词典中的单词。
- unk 不在数据集中,这就是 corporations 这个单词的情况。这解释了为什么在这种情况下它不在词典中。
- 如果用户向变换器发送包含未分词的 token 的输入,unk 将出现在生产中。
- unk 对于数据集的使用不重要,但对于变换器的使用是重要的。
如果变换器在某些情况下产生糟糕的结果,问题清单将继续增加。我们可以在训练阶段将0.8视为特定下游任务的变换器模型的出色性能。但在现实生活中,谁愿意与一个在20%的时间内出错的系统一起工作:
- 医生?
- 律师?
- 核电厂维护团队? 在社交媒体这种模糊的环境中,0.8是可以接受的,因为其中许多消息本身就缺乏适当的语言结构。
现在来到最糟糕的部分。假设一个自然语言处理团队发现了这个问题,并尝试使用字节级BPE来解决它,就像我们在本书的整个章节中一直在做的那样。如果需要,花几分钟回到第4章,从头开始预训练一个RoBERTa模型,第3步:训练分词器。
如果一个团队只使用字节级BPE来解决问题,噩梦就开始了:
- unk 将被分解成单词片段。例如,我们可能会得到 corporations 被分解为 corp + o + ra + tion + s。其中一个或几个这些标记很可能存在于数据集中。
- unk 将成为由数据集中存在但不传达原始 token 意义的标记表示的子单词集合。
- 变换器将训练良好,没有人会注意到 unk 被分成片段并毫无意义地训练。
- 变换器甚至可能会产生出色的结果,并将其性能从0.8提高到0.9。
- 所有人都会为此鼓掌,直到专业用户在关键情况下应用错误的结果。例如,在英语中,corp 可能意味着公司或军士。这可能会引发混淆和 corp 与其他单词之间的不良关联。
我们可以看到,社交媒体的标准可能足够用于处理琐碎的话题。但在实际的企业项目中,将需要大量的工作来创建一个与数据集匹配的预训练分词器。在现实生活中,数据集每天都会随着用户输入而增长。用户输入会成为应该定期训练和更新的模型数据集的一部分。
例如,确保质量控制的一种方式可以通过以下步骤:
- 使用字节级BPE算法训练一个分词器。
- 使用本章的“控制分词化数据”部分中将创建的程序来控制结果。
- 还可以使用Word2Vec算法训练一个分词器,该分词器仅用于质量控制,然后解析数据集,查找 unk 标记,并将其存储在数据库中。运行查询以检查是否缺少关键单词。
也许检查过程中的如此详细似乎是不必要的,您可能会倾向于依赖变换器对看不见的单词进行推断的能力。
然而,我建议在具有关键决策制定的战略项目中运行多种不同的质量控制方法。例如,在法律法规的法律摘要中,一个词可以在法庭上的胜负之间起到关键作用。在航空航天项目(飞机、火箭)中,有一个0错误容忍标准。
您运行的质量控制过程越多,您的变换器解决方案就会越可靠。
我们可以看到,获得可靠数据集需要大量的工作!每一篇关于变换器的论文都以某种方式提到了创建可接受数据集所需的工作。嘈杂的关系也会导致问题。
情况2:嘈杂的关系
在这种情况下,数据集包含了单词 “etext” 和 “declaration”:
#@title Case 2: Noisy Relationship
word1="etext";word2="declaration"
print("Similarity",similarity(word1,word2),word1,word2)
此外,它们都出现在分词词典中:
Similarity [[0.880751]] etext declaration
更重要的是,它们的余弦相似度似乎对其预测感到确信,并且超过了0.5。算法的随机性可能会在不同的运行中产生不同的结果。
在琐碎或社交媒体水平上,一切看起来都很好。
然而,在专业水平上,结果是灾难性的!
etext 指的是Project Gutenberg网站上每本电子书前言中的前言,如本章的“匹配数据集和分词器”部分所解释的。变换器的特定任务目标是什么:
- 理解编辑的前言?
- 还是理解书的内容?
这取决于变换器的使用,可能需要几天时间来解决。例如,假设一位编辑希望自动理解前言并使用变换器生成前言文本。我们应该取出内容吗?
declaration 是与《独立宣言》的实际内容相关的有意义的单词。
etext 是Project Gutenberg添加到其所有电子书中的前言的一部分。
这可能会产生错误的自然语言推理,例如,当变换器被要求生成文本时,etext 是一项声明。
让我们探讨一个缺失单词的问题。
情况3:在文本中但不在词典中的单词
在某些情况下,一个单词可能在文本中但不在词典中。这将扭曲结果。
让我们看看单词 “pie” 和 “logic”:
#@title Case 3: word in text, not in dictionary
word1="pie";word2="logic"
print("Similarity",similarity(word1,word2),word1,word2)
单词 “pie” 不在词典中:
pie :[unk] key not found in dictionary
Similarity 0 pie logic
我们可以假设单词 “pie” 应该在分词词典中。但如果它不在词典中或其他单词也不在呢?单词 “pie” 不在文本文件中。
因此,我们应该在流程中拥有检测不在词典中的单词以实施更正或替代方案的功能。此外,我们应该在流程中拥有检测数据集中可能重要的单词的功能。
让我们看看我们在面对罕见单词时会遇到的问题。
情况4:罕见的单词
罕见的单词对于超出简单应用的特定任务的变换器输出产生毁灭性的影响。
管理罕见单词扩展到自然语言的许多领域。例如:
- 罕见的单词可能出现在数据集中,但被忽视,或者模型被糟糕地训练以处理它们。
- 罕见的单词可以是医学、法律、工程术语或其他专业行话。
- 罕见的单词可以是俚语。
- 英语有数百种变体。例如,在美国、英国、新加坡、印度、澳大利亚和许多其他国家的某些地方使用不同的英语词汇。
- 罕见的单词可以来自几个世纪前写的被遗忘的文本,只有专家使用。
例如,在这种情况下,我们使用了单词 “justiciar”:
#@title Case 4: Rare words
word1="justiciar";word2="judgement"
print("Similarity",similarity(word1,word2),word1,word2)
与 “judgement” 的相似性是合理的,但应该更高:
Similarity [[0.6606605]] justiciar judgement
你可能认为单词 “justiciar” 太牵强了。分词器从早在13世纪初的《大宪章》中提取了它。不幸的是,每次运行后,程序都会变得混乱,我们将获得意想不到的结果。
然而,《大宪章》的几个条款在21世纪的英格兰仍然有效!例如,第1、13、39和40条款仍然有效!
《大宪章》最著名的部分是以下摘录,它包含在数据集中:
(39) No free man shall be seized or imprisoned, or stripped of his
rights or possessions, or outlawed or exiled, or deprived of his
standing in any other way, nor will we proceed with force against him,
or send others to do so, except by the lawful judgement of his equals
or by the law of the land.
(40) To no one will we sell, to no one deny or delay right or justice.
如果我们在律师事务所中实施一个变换器模型来总结文件或执行其他任务,我们必须小心谨慎!
现在让我们看看一些方法,可以用来解决罕见单词问题。
情况5:替换罕见单词
替换罕见单词本身就是一个项目。这项工作通常保留给特定任务和项目。假设一个公司的预算可以覆盖在航空领域建立一个知识库的成本,那么值得花费必要的时间来查询分词目录,找出被忽略的单词。
问题可以按主题分组,解决,并定期更新知识库。
在情况4中,我们遇到了单词 “justiciar”。如果我们回溯其起源,可以看到它来自法国诺曼底语言,是法国类似拉丁语的单词 “judicaire” 的词根。
我们可以用 “judge” 替换单词 “justiciar”,这传达了相同的元概念:
#@title Case 5: Replacing rare words
word1="judge";word2="judgement"
print("Similarity",similarity(word1,word2),word1,word2)
这产生了一个有趣的结果,但由于算法的不确定性,我们仍然需要小心:
Similarity [[0.7962761]] judge judgement
我们也可以保留单词 “justiciar”,但尝试使用该词的现代含义并与 “judge” 进行比较。您可以尝试实施情况5:替换罕见单词:
word1="justiciar";word2="judge"
print("Similarity",similarity(word1,word2),word1,word2)
无论如何,一些罕见的单词需要被更常见的单词替代。
结果将是令人满意的:
Similarity [[0.9659128]] justiciar judge
我们可以创建具有替代词的查询,运行这些查询,直到找到相关性超过0.9的情况,例如。而且,如果我们管理一个关键的法律项目,我们可以将包含任何种类的罕见单词的重要文件翻译成标准英语。因此,变换器在NLP任务中的性能将提高,并且公司的知识库将逐渐增加。
现在让我们看看如何使用余弦相似性进行蕴涵验证。
情况6:蕴涵
在这种情况下,我们对字典中的单词感兴趣,并按固定顺序进行测试。
例如,让我们看看在我们的相似性函数中,“pay” + “debt” 是否有意义:
#@title Case 6: Entailment
word1="pay";word2="debt"
print("Similarity",similarity(word1,word2),word1,word2)
结果令人满意:
Similarity [[0.89891946]] pay debt
我们可以检查数据集中的多个词对,并检查它们是否具有意义。例如,这些词对可以从法律部门的电子邮件中提取。如果余弦相似性超过0.9,那么可以剥离电子邮件中的无用信息,并将内容添加到公司的知识库数据集中。
现在让我们看看预训练的分词器与NLP任务的匹配情况。
具体词汇的标准NLP任务
这一部分着重介绍本章中的情况4:罕见单词 和情况5:替换罕见单词,它们源自本章的Word2Vec分词部分。
我们将使用Training_OpenAI_GPT_2_CH09.ipynb,这是我们在第7章《超人类变换器与GPT-3引擎的崛起》中用于训练数据集的笔记本的重命名版本。
笔记本进行了两个更改:
- 将数据集dset更名为mdset,其中包含医学内容
- 添加了一个Python函数,用于控制使用字节级BPE进行分词的文本
我们不会在这里详细描述Training_OpenAI_GPT_2_CH09.ipynb,因为我们在第7章和附录III、IV中已经介绍过。在开始之前,请确保按照第7章中的说明上传必要的文件。
您可以根据需要对模型进行训练,没有时间限制。您可以随时中断以保存模型。
文件在GitHub的Chapter09的gpt-2-train_files目录中。尽管我们使用的是第7章相同的笔记本,但请注意该数据集dset在目录和代码中现在被命名为mdset。
首先,让我们使用经过训练以理解医学内容的GPT-2模型生成一个无条件的示例。
使用GPT-2生成无条件样本
在这一部分,我们将深入研究了解变换器的内部工作原理。当然,我们可以跳过整章,直接使用OpenAI的API。然而,一个4.0的AI专家必须成为一个AI大师,通过预处理流程向Transformer模型展示应该做什么,而不是含糊地告诉它。为了向Transformer模型展示应该做什么,必须了解Transformer模型的工作原理。
在情况4:罕见单词 和情况5:替换罕见单词中,我们看到罕见单词可能是某个领域中使用的词汇、古英语、世界各地英语的变种、俚语等。
2020年,新闻中充斥着与COVID-19爆发有关的医学术语。在本节中,我们将看到GPT-2变换器如何处理医学文本。
要编码和训练的数据集包括Martina Conte和Nadia Loy(2020年)的论文,题为“Multi-cue kinetic model with non-local sensing for cell migration on a fibers network with chemotaxis”。
这个标题本身不容易理解,其中包含一些罕见的词汇。
加载位于gpt-2-train_files目录中的文件,包括mdset.txt。然后运行代码,如第7章“GPT-3引擎的崛起”中所解释的那样。您可以按照第7章的指导逐个单元格运行这段代码。特别要注意遵循说明,确保激活tf 1.x。确保运行步骤4,然后重新启动运行时,然后再次运行步骤4的tf 1.x单元格,然后继续。否则,您将在笔记本中遇到错误。在本节中,我们将亲自动手使用低级原始的GPT-2代码,而不是API。
在将模型训练到医学数据集后,您将进入无条件示例单元格,即第11步:“生成无条件示例”:
#@title Step 11: Generating Unconditional Samples
import os # import after runtime is restarted
os.chdir("/content/gpt-2/src")
!python generate_unconditional_samples.py --model_name '117M'
运行该单元格,并在需要时停止。它将生成一个随机的输出:
community-based machinery facilitates biofilm growth. Community members place biochemistry as the main discovery tool to how the cell interacts with the environment and thus with themselves, while identifying and understanding all components for effective Mimicry.
2. Ol Perception
Cytic double-truncation in phase changing (IP) polymerases (sometimes called "tcrecs") represents a characteristic pattern of double-crossing enzymes that alter the fundamental configuration that allows initiation and maintenance of process while chopping the plainNA with vibrational operator. Soon after radical modification that occurred during translational parasubstitution (TMT) achieved a more or less uncontrolled activation of SYX. TRSI mutations introduced autophosphorylation of TCMase sps being the most important one that was incorporated into cellular double-triad (DTT) signaling across all
cells, by which we allow R h and ofcourse an IC 2A- >
.../...
如果我们仔细观察输出,我们会注意到以下几点:
- 生成的句子结构相对可接受
- 输出的语法不算糟糕
- 对于非专业人士来说,输出可能看起来类似人类的
然而,内容毫无意义。Transformer 无法生成与我们训练的医学论文相关的真实内容。要获得更好的结果需要付出艰苦的努力。当然,我们总是可以增加数据集的大小。但它是否包含我们正在寻找的内容呢?我们会不会在更多数据中找到错误的相关性呢?例如,想象一个涉及 COVID-19 的医学项目,数据集包含以下句子:
- COVID-19 不是一种危险的病毒,但它就像普通的流感。
- COVID-19 是一种非常危险的病毒。
- COVID-19 不是病毒,而是由实验室创造的东西。
- COVID-19 绝对不是由实验室创造的!
- 疫苗是危险的!
- 疫苗是救命的!
- 政府没有正确管理大流行。
- 政府采取了必要的措施。
以及更多相互矛盾的句子。这些差异证实了专门针对医疗保健项目、航空航天、交通等关键领域需要自定义数据集和分词器。
想象一下,你有一个包含数十亿字的数据集,但内容如此矛盾和嘈杂,无论你尝试什么,都无法获得可靠的结果!
这可能意味着数据集必须更小,并且仅限于科学论文的内容。但即便如此,科学家之间也经常意见不一。
结论是,要产生可靠的结果需要付出大量的辛苦工作和一个坚实的团队。
现在让我们尝试对 GPT-2 模型进行条件化。
生成已训练的条件样本
在本节中,我们将转到笔记本的第12步:交互式上下文和完成示例单元格并运行它:
#@title Step 12: Interactive Context and Completion Examples
import os # import after runtime is restarted
os.chdir("/content/gpt-2/src")
!python interactive_conditional_samples.py --temperature 0.8 --top_k 40 --model_name '117M' --length 50
工业4.0的AI专家将更少关注代码,而更多关注如何向转换模型展示应该执行的操作。每个模型都需要一定程度的指导,而不仅仅是使用无条件的数据来模糊地告诉它做某事。
我们通过输入医学论文的一部分来对GPT-2模型进行条件设定:
During such processes, cells sense the environment and respond to external factors that induce a certain direction of motion towards specific targets (taxis): this results in a persistent migration in a certain preferential direction. The guidance cues leading to directed migration may be biochemical or biophysical. Biochemical cues can be, for example, soluble factors or growth factors that give rise to chemotaxis, which involves a mono-directional stimulus. Other cues generating mono-directional stimuli include, for instance, bound ligands to the substratum that induce haptotaxis, durotaxis, that involves migration towards regions with an increasing stiffness of the ECM, electrotaxis, also known as galvanotaxis, that prescribes a directed motion guided by an electric field or current, or phototaxis, referring to the movement oriented by a stimulus of light [34]. Important biophysical cues are some of the properties of the extracellular matrix (ECM), first among all the alignment of collagen fibers and its stiffness. In particular, the fiber alignment is shown to stimulate contact guidance [22, 21]. TL;DR:
我们在输入文本的末尾添加了”TL;DR:”,告诉GPT-2模型总结我们对其进行了条件设置的文本。输出在语法和语义上都是有意义的:
the ECM of a single tissue is the ECM that is the most effective.
To address this concern, we developed a novel imaging and immunostaining scheme that, when activated, induces the conversion of a protein to its exogenous target
由于输出是不确定的,我们也可能获得这个响应:
Do not allow the movement to be directed by a laser (i.e. a laser that only takes one pulse at a time), but rather a laser that is directed at a target and directed at a given direction. In a nutshell, be mindful.
这个例子和本章节的结论是,例如,通过在大量随机网络爬虫数据上进行预训练的转换模型,将会教给变压器英语。但是,像我们一样,一个变压器也需要在特定领域接受培训,以成为该领域的专家。
让我们深入研究并控制标记化数据。
控制标记化数据
这一部分将读取GPT-2模型使用其预训练的标记化工具编码的第一个单词。
在运行代码单元格时,请在运行后续单元格之前停止一个单元格。
我们将前往Training_OpenAI_GPT_2_CH09.ipynb笔记本的“附加工具:控制标记化数据”单元格。此单元格是专门为本章添加到笔记本中的。
该单元格首先解压out.npz,其中包含编码的医学论文,该论文位于数据集mdset中。
#@title Additional Tools : Controlling Tokenized Data
#Unzip out.npz
import zipfile
with zipfile.ZipFile('https://b2.7b2.com/content/gpt-2/src/out.npz', 'r') as zip_ref:
zip_ref.extractall('/content/gpt-2/src/')
out.npz 已解压缩,我们可以读取 arr_0.npy,其中包含我们正在寻找的编码数据集的NumPy数组:
#Load arr_0.npy which contains encoded dset
import numpy as np
f=np.load('https://b2.7b2.com/content/gpt-2/src/arr_0.npy')
print(f)
print(f.shape)
for i in range(0,10):
print(f[i])
输出是数组的前几个元素:
[1212 5644 326 ... 13 198 2682]
我们现在将打开 encoder.json 并将其转换为Python字典:
#We first import encoder.json
import json
i=0
with open("https://b2.7b2.com/content/gpt-2/models/117M/encoder.json", "r") as read_file:
print("Converting the JSON encoded data into a Python dictionary")
developer = json.load(read_file) #converts the encoded data into a Python dictionary
for key, value in developer.items(): #we parse the decoded json data
i+=1
if(i>10):
break;
print(key, ":", value)
最后,我们显示我们编码数据集的前500个标记的键和值:
#We will now search for the key and value for each encoded token
for i in range(0,500):
for key, value in developer.items():
if f[i]==value:
print(key, ":", value)
mdset.txt的前几个单词如下:
This suggests that
我添加了这些词以确保GPT-2的预训练分词器可以轻松识别它们,事实正是如此:
This : 1212
Ġsuggests : 5644
Ġthat : 326
我们可以轻松识别前面带有初始空格字符(Ġ)的初始标记。然而,让我们看看医学论文中的以下单词:
amoeboid
“amoeboid” 是一个不常见的单词。我们可以看到 GPT-2 的分词器将其分解为子词:
Ġam : 716
o : 78
eb : 1765
oid : 1868
让我们忽略空格,看看发生了什么。amoeboid 被拆分成了 am + o + eb + oid。我们必须同意这里没有未知的标记:[unk]。这是由于使用的字节级 BPE 策略。
然而,变压器的注意层可能会关联:
- am 与其他序列,例如 “I am”
- o 与任何被拆分并包含 o 的序列
- oid 与另一个包含 oid 的序列,可能与某些算法相关的 tabloid
这实际上不是一个好消息。让我们看看以下单词:
amoeboid and mesenchymal
输出清楚显示了 “and”。至于其余部分,这些标记令人困惑:
Ġam : 716
o : 78
eb : 1765
oid : 1868
Ġand : 290
Ġmes : 18842
ench : 24421
ym : 4948
al : 282
你可能会想为什么这是一个问题。答案可以用一个词来总结:多义性。如果我们使用 word2vec 标记生成器,字典可能不包含像 amoeboid 这样的罕见词汇,结果可能是一个未知标记。
如果我们使用字节级 BPE,通常会获得更好的结果,因为我们排除了较少的相同词的变体,比如 go 和 go + ing。
然而,在 amoeboid 中的 am 标记引入了多义性问题。am 可能是一种前缀,也可能是 am 一词,例如 I + am,或者是 am + bush 中的子词。注意力层可能会将一个标记中的 am 与另一个 am 相关联,从而创建不存在的关系。这就定义了自然语言理解中多义性的核心问题。
我们可以说进展正在取得,但我们需要更加努力来改进自然语言处理。
在本章的示例中,我们已经介绍了一些在实际项目中会遇到的日常问题。花一些时间尝试你认为有用的示例。
在我们结束之前,我们将使用一个探测任务来验证一个变压器模型提供的自然语言理解水平。
探索GPT-3的范围
即使像OpenAI GPT-3这样强大的变换器也有其限制。让我们看看GPT-3如何对待单词”amoeboid”,这个词更接近医学术语而不是主流词汇。在许多项目中,我们需要使用技术术语。匹配数据集需要对变换器如何组织其字典和嵌入进行质量控制。
我们人类可以检测错误并纠正他人。例如,在本章中,我们在本章的”控制标记数据”部分探讨了”amoeboid”一词。
让我们首先问GPT-3″amoeboid”是什么意思:
“amoeboid”(类似变形虫的)是一个形容词,然而GPT-3的输出中却表示它是一个名词。
A: Amoeboid is a noun which means "resembling an amoeba"
然后,我们向GPT-3提出了一个更为精确的问题,但依然获得了一个错误的答案:
Q: Is amoeboid a noun or an adjective?
A: Amoeboid is a noun.
最后,我们坚持要求清晰的定义,并获得了正确的答案:
Q: What does amoeboid mean in medical terms?
A: Amoeboid means "resembling an amoeba".
在现实项目中,更重要的是理解一个词的定义,还是识别它在句子中的角色,例如形容词或名词?
也许语法方面对于教育文法学校项目很重要,但对于企业供应链、金融和电子商务应用来说可能不那么重要。
正如我们在第7章《GPT-3引擎的超人类转型》中所看到的,OpenAI GPT-3可以在这两种情况下进行微调。
本节的结论是,我们必须确保我们在训练好的变换器模型中有所有所需的数据。如果没有,分词过程将不完整。也许我们应该拿一本医学词典,创建一个包含特定词汇的大型医学文章语料库。然后,如果模型还不够准确,我们可能需要对我们的数据集进行分词,并从头开始训练一个模型。
2022年的开发人员将进行更少的开发工作,但仍需要进行大量思考和设计!
现在让我们总结这一章,继续进行另一个自然语言理解任务。
总结
在本章中,我们测量了分词和随后的数据编码过程对变换器模型的影响。一个变换器模型只能关注堆栈的嵌入和位置编码子层中的标记。它不管模型是编码器-解码器、编码器-only还是解码器-only模型。也不管数据集是否足够好来进行训练。
如果分词过程出现问题,即使只有部分问题,我们运行的变换器模型也会错过关键标记。
首先,我们看到对于标准语言任务,原始数据集可能足够训练一个变换器。
然而,我们发现,即使预训练的分词器经过了数十亿单词,它只会创建一个包含它遇到的词汇小部分的词典。像我们一样,如果这些词汇也经常使用,分词器会捕捉所学语言的精髓,只记住最重要的单词。这种方法对于标准任务很有效,但在特定任务和词汇方面会产生问题。
然后,我们寻找了一些想法,其中包括调整我们希望处理的文本的语言检查方法,就像分词器思考和编码数据的方式。
我们将这种方法应用于了GPT-2的无条件和有条件任务。
最后,我们分析了数据分词和与GPT-3的数据匹配的限制。您可以从本章中获得的教训是,AI专家还将在相当长的时间内存在!
在下一章《基于BERT的变换器的语义角色标注》中,我们将深入探讨自然语言理解,并使用BERT模型要求变换器解释一个句子的含义。