AGI 之 【Hugging Face】 的【未来发展趋势】之 [ Transformer的扩展 ] / [ 多模态的 Transformer ]的简单整理
目录
AGI 之 【Hugging Face】 的【未来发展趋势】之 [ Transformer的扩展 ] / [ 多模态的 Transformer ]的简单整理
一、简单介绍
二、Transformer的扩展
1、扩展准则
2、扩展挑战
3、注意力效率提升
4、稀疏化注意力
5、线性化注意力
三、其他应用领域
1、图像处理
2、表格处理
四、多模态的Transformer
1、语音和文本处理
2、图像和文、本处理
3、继续前行的建议
附录
一、当前案例环境 package 的 版本如下
一、简单介绍
AGI,即通用人工智能(Artificial General Intelligence),是一种具备人类智能水平的人工智能系统。它不仅能够执行特定的任务,而且能够理解、学习和应用知识于广泛的问题解决中,具有较高的自主性和适应性。AGI的能力包括但不限于自我学习、自我改进、自我调整,并能在没有人为干预的情况下解决各种复杂问题。
- AGI能做的事情非常广泛:
跨领域任务执行:AGI能够处理多领域的任务,不受限于特定应用场景。
自主学习与适应:AGI能够从经验中学习,并适应新环境和新情境。
创造性思考:AGI能够进行创新思维,提出新的解决方案。
社会交互:AGI能够与人类进行复杂的社会交互,理解情感和社会信号。
- 关于AGI的未来发展前景,它被认为是人工智能研究的最终目标之一,具有巨大的变革潜力:
技术创新:随着机器学习、神经网络等技术的进步,AGI的实现可能会越来越接近。
跨学科整合:实现AGI需要整合计算机科学、神经科学、心理学等多个学科的知识。
伦理和社会考量:AGI的发展需要考虑隐私、安全和就业等伦理和社会问题。
增强学习和自适应能力:未来的AGI系统可能利用先进的算法,从环境中学习并优化行为。
多模态交互:AGI将具备多种感知和交互方式,与人类和其他系统交互。
Hugging Face作为当前全球最受欢迎的开源机器学习社区和平台之一,在AGI时代扮演着重要角色。它提供了丰富的预训练模型和数据集资源,推动了机器学习领域的发展。Hugging Face的特点在于易用性和开放性,通过其Transformers库,为用户提供了方便的模型处理文本的方式。随着AI技术的发展,Hugging Face社区将继续发挥重要作用,推动AI技术的发展和应用,尤其是在多模态AI技术发展方面,Hugging Face社区将扩展其模型和数据集的多样性,包括图像、音频和视频等多模态数据。
- 在AGI时代,Hugging Face可能会通过以下方式发挥作用:
模型共享:作为模型共享的平台,Hugging Face将继续促进先进的AGI模型的共享和协作。
开源生态:Hugging Face的开源生态将有助于加速AGI技术的发展和创新。
工具和服务:提供丰富的工具和服务,支持开发者和研究者在AGI领域的研究和应用。
伦理和社会责任:Hugging Face注重AI伦理,将推动负责任的AGI模型开发和应用,确保技术进步同时符合伦理标准。
AGI作为未来人工智能的高级形态,具有广泛的应用前景,而Hugging Face作为开源社区,将在推动AGI的发展和应用中扮演关键角色。
(注意:以下代码运行,可能需要科学上网)
二、Transformer的扩展
在2019年,研究员Richard Sutton(https://oreil.ly/119br)写了一篇题为“The Bitter Lesson”(惨痛的教训)(https://oreil.ly/YtD3V)的具有争议的文章,文中指出:
从人类历经了70年的AI研究中得到的最大教训是,利用算力一般最终都能解决问题,而且可选的算力范围很大……为了寻求能在短期带来较大的提升,研究人员只能依靠人类的领域知识来进行优化,但从长远来看,最重要的还是需要寻求更好地利用算力的方法。二者并不矛盾,但在实践当中往往会产生冲突……人类的知识往往会让方法复杂化,使得不能很好地利用算力。
这篇文章举了几个业界历史上的例子,比如利用AI下围棋或者象棋,基于人类领域知识的程序最终被算力的提升所超越,Sutton称之为AI研究领域的“惨痛教训”。
我们必须从中吸取惨痛的教训,用固有的思维模式来解决问题是行不通的……但是从中我们可以学到:一些常用的工程方法也可以带来很大的提升,这种方法就是扩容,搜索领域和机器学习领域都能使用这种方法提升效率。
有迹象表明,Transformer模型也经历了类似的演化。虽然许多基于BERT和GPT的模型此后一直专注在架构的调整或预训练目标之上,但2021年最受关注的模型还是GPT-3,它基本是原始模型的扩展版本,并没有多少架构上的改进。在下图中,我们可以看到自2017年以来,最原始的Transformer架构发布之后的大模型更迭时间表,可以看出在短短几年的时间,模型规模居然增加了4个以上的数量级!
J. Kaplan et al., “Scaling Laws for Neural Language Models”(https://arxiv.org/abs/2001.08361),(2020).
这种急剧增长的趋势是由实验结论来推动的,即大型语言模型在下游任务中往往表现更好,且在100亿~1000亿参数范围内出现了一些有趣的应用方式,比如零样本学习和少样本学习。然而,参数数量并不是影响模型性能的唯一因素,计算量和训练数据也需要同步扩展,才能跟得上模型的训练需要,像GPT-3这样的大型语言模型就大概花费了460万美元(https://oreil.ly/DUVcq)来训练。因此,提前预估模型的性能,就显得很有必要。令人惊讶的是,语言模型的性能似乎与模型大小以及其他一些因素遵循一种幂律关系,这种关系被应用在了模型的扩展性上面 。让我们来看看这个令人兴奋的研究领域。
1、扩展准则
数据集大小可以用词元的数量来度量,而模型大小不包括嵌入层中的参数。
扩展准则通过研究语言模型在不同的计算量C、数据集大小D和模型大小N之下的表现来量化扩展范式。对于像GPT中的自回归模型,其损失曲线如下图所示,其中每条曲线都代表一个模型的训练过程。
从以上的损失曲线中,可以得出下面的结论:
- 性能与模型扩展规模的关系
尽管许多NLP领域的研究人员专注于模型架构调整或超参数优化(如调整层数或注意力头数),以此来提升其在一组固定数据集上的性能。其实也可以关注模型的扩展方面,研究如何调整N、C和D来获取较高的性能表现。
- 平滑幂律
α
T. Henighan et al., “Scaling Laws for Autoregressive Generative Modeling”(https://arxiv.org/abs/2010.14701),(2020).
测试得出,损失L与N、C和D中的每一个都有几个数量级的幂律关系(幂律关系在对数尺度上是线性的)。对于X=N、C、D,我们可以将这些幂律关系表示为L(X)~1/X,其中α是一个扩展指数,由图11-2的损失曲线的拟合来决定。αX的值一般在0.05~0.095之间,这些幂律关系的一个主要特点是,可以根据规律来推断随训练时间的增加,会出现什么样的损失结果。
- 采样效率
通过比较损失曲线在一定数量的训练步骤中较规律的部分可以看出,大型模型能够在较少的训练步骤下达到与小型模型相同的性能,这说明如果只是单纯地扩大模型的规模,其收益会越来越小。
不过令人惊讶的是,业界还总结出了其他模态的扩展规律,比如图像、视频和数学问题的解决,如下图所示。
目前仍然不确定Transformer语言模型是否符合幂律扩展规律。不过用这种方法来预测一些大型且昂贵的模型效果不失为一种解决方案,而不必去做繁杂的训练工作。然而,模型扩展并不是看上去那么容易,下面我们看看该领域的几个挑战。
2、扩展挑战
虽然将模型扩大规模在理论上听起来简单(似乎只需要增加更多的层),但在实践中会遇到很多挑战,如下所示:
- 基础设施
在实际环境中,我们可能需要去管理具有数千个物理节点的基础设施,其中还包括GPU的配套管理。只看数字就知道这其中会有很多问题:节点的可用性如何?节点的通信瓶颈是否存在?解决这些问题需要依赖非常专业的工程团队,以及科学的管理方式。
- 成本
但是,最近业界提出了一种新的分布式深度学习框架,可以使小公司协调计算资源来进行预训练任务。参见M. Diskin等人的“Distributed Deep Learning in Open Collaborations”(https://arxiv.org/abs/2106.10207),(2021).
ML从业者需要借助性能强大的GPU才能快速完成模型的训练与推理,但GPU往往价格不菲。当需要进行大规模学习任务的时候,预算更是一再拔高。比如训练一个GPT-3这样规模的模型,就需要上百万美元,这不是所有公司都能承受的 。
- 数据集整理
一个模型的好坏很大程度上取决于训练数据。训练大模型更是需要大规模、高质量的数据集。当使用庞大的数据集训练模型时,我们很难知晓其中所有语料的质量,这样在做预处理的时候就很有挑战性。此外,还需要控制倾向性,例如,如果数据集中包含大量的性别歧视和种族主义的语料,那么训练出的模型也会具有这些特征。另外一点则是需要注意数据集中的敏感信息,例如身份证号码、电话等。
- 模型评估
当模型训练完成,又会面临另一个挑战,那就是在下游任务上评估模型。这又需要耗费时间和精力。此外,我们需要测试模型是否有较大倾向性的内容生成,以避免之后在使用过程中出现不必要的麻烦。
- 模型部署
在模型训练与评估完成后,如何将它以服务的方式提供给使用者也是一大挑战,这就是模型的工程化问题。在第8章中,我们介绍了蒸馏、剪枝和量化等方法,来解决一些工程化问题。但是,如果模型大小高达几百GB,用这些方法是肯定不够的。一些提供模型托管服务的公司,如OpenAI API(https://beta.openai.com)或者Hugging Face Accelerated Inference API(https://oreil.ly/E4q3b),可以帮助解决这些问题。
以上列举的这些并不是所有的挑战,我们在实际操作的时候还可能遇到更多的情况。虽然我们自行研究某些大模型非常困难,但目前有两个社区开放项目,旨在让更多人可以参与到大模型的研究中来:
- BigScience
这是一个在2021年诞生的研讨会,主要研究大型语言模型。该研讨会围绕模型的常见问题,如能力、局限性、潜在改进点、偏见、伦理、环境影响、在AI业界的作用等,展开讨论与反思,以及以研究为目的来构建一些模型和数据集,且为此分配了庞大的计算资源(上千个GPU)。如果你想加入的话,可以访问项目网站(https://oreil.ly/13xfb)。
- EleutherAI
该组织由志愿研究员、工程师和开发者组成,专注于AI领域的协调、扩展和开源的研究。它的目标是训练并开源一个GPT-3大小的模型,目前该小组已经发布了一些有影响力的模型,如GPT-Neo(https://oreil.ly/ZVGaz)和GPT-J(https://oreil.ly/Kup60),它们拥有60亿级别的参数,目前是零样本训练领域表现最好的公开且可用的Transformer模型。你可以在其网站上获取更多信息(https://eleuther.ai)。
现在,我们探讨了如何在计算量、模型大小和数据集大小之间来扩展Transformer模型,下面介绍另一个火爆的研究领域:如何让自注意力机制更有效率。
3、注意力效率提升
尽管自注意力的标准实现具有O(n²)的时间和空间复杂度,但谷歌的研究人员最近发表的一篇论文(https://arxiv.org/abs/2112.05682)表明通过简单的操作,即重新排序可以将空间复杂度降低到O(log n)。
本书专门介绍过自注意力机制在Transformer的架构中起着核心作用。毕竟Transformer的原始论文就叫作“Attention Is All You Need”!然而,自注意力却有一个关键挑战:由于权重是根据对序列中所有词元进行配比产生的,因此当试图处理长文本或将Transformer用在智能语音与计算机视觉领域等时,这一层就会成为计算瓶颈。从时间复杂度和空间复杂度角度来看,Transformer架构的自注意力层的规模符合O(n)规律,其中n代表序列长度。
因此,业界最近关于Transformer的研究方向都围绕着提升自注意力层的效率,如下图所示。
Yi Tay et al., “Efficient Transformers:A Survey”(https://arxiv.org/abs/2009.06732),(2020).
4、稀疏化注意力
降低自注意力层中的计算量的一个简单方法,就是限制由预定义模式产生的query-key对的数量。许多文献都提到了这一点,但绝大多数都可以用下图中的“原子”模式来解释。
T. Lin et al., “A Survey of Transformers”(https://arxiv.org/abs/2106.04554),(2021).
图中所有模式解释如下:
- 全局注意力机制
在序列中定义几个特殊的词元,并允许其注意其他所有的词元。
- 局部注意力机制
在对角线区域计算注意力分数。
- 扩张注意力机制
通过使用具有间隙的扩张窗口,跳过一些query-key对。
- 随机注意力机制
对每次查询随机提取几个key来计算注意力分数。
- 本地块注意力机制
将序列划分成若干个块,并将注意力限制在每个块内。
在实践中,大多数具有稀疏注意力的Transformer模型一般都使用原子稀疏混合模式来生成注意力矩阵,如图11-6所示。比如Longformer模型(https://oreil.ly/F7xCY)使用全局和局部注意力的混合模式,BigBird模型(https://oreil.ly/yFPyj)则在混合模式中又加入了随机注意力。在注意力矩阵中引入稀疏性能够使模型处理更长的序列,这样的Longformer模型和BigBird模型能将处理的最大序列长度扩增到4096个词元,比BERT模型大8倍。
还可以通过数据驱动的方式将稀疏模式运用到模型,这类方法的基本思想是将词元聚集成为块。例如,Reformer模型(https://oreil.ly/yIVvX)使用哈希函数将相似的词元聚集到一起成为块。
以上介绍了如何运用稀疏性来降低自注意力的复杂性方法,接下来我们介绍一种直接改变操作的方式。
5、线性化注意力
另一种能使自注意力更高效的方法是改变计算注意力分数时的操作顺序。回想一下,为了计算query和key的自注意力分数,我们引入了一个相似度函数,对于Transformer来说,它只做了一个简单的点积。然而,对于一般的相似度函数sim(q,k),我们可以用以下公式来表示注意力输出:
线性化注意力机制的诀窍是将相似度函数表示为一个核函数,将操作分解为两部分:
其中φ是一个高维的特征图,由于φ(Q)与j和k均无关,因此注意力输出形式可以变换为
i
A. Katharopoulos et al., “Transformers Are RNNs: Fast AutoregressiveTransformerswith Linear Attention”(https://arxiv.org/abs/2006.16236),(2020); K. Choromanski et al., “Rethinking Attention with Performers”(https://arxiv.org/abs/2009.14794),(2020).
通过先计算和∑kφ(K),就可以有效地将自注意力的时间和空间复杂度线性化。如图比较了这两种方法,采用这种线性化自注意力的模型有Transformer和Performer。
k
三、其他应用领域
与迁移学习结合,借助文本语料训练语言模型,是Transformer模型大获成功的主要原因。一方面,丰富的文本可以实现大模型的自监督训练;另一方面,像文本分类和问答对提取这样的文本类需求应用广泛,驱使业界不断探索新的策略,解决现实问题。
然而,这些解决问题的方法也有局限性,包括:
- 人类报告偏见
J. Gordon and B. Van Durme,“Reporting Bias and Knowledge Extraction”(https://openreview.net/pdf?id=AzxEzvpdE3Wcy),(2013).
文本中的事件频率并不能代表真实事件频率,仅根据互联网上的文本语料进行训练的模型很可能具有人类报告偏见的现象。
- 常识
常识是人类推理出的一种普遍结果,但很少会被书面化。因此,根据文本训练的语言模型可能知道很多事实性知识,但缺乏常识性推理。
- 事实
语言模型都是以概率的方式工作,不可能直接存储事实,可能会导致产生出与事实不相符的文本。同样道理,这种模型虽然能够检测到命名的实体,但很难直接获取关于它们的信息。
-
模态
语言模型没法直接泛化到其他模态,比如处理音频、视频或表格数据。
因此,如果能够解决模态的限制,就能解决很多问题,最近,Transformer在新的模态方面取得了一些成绩,甚至在构建多模态模型方面也取得了进展。下面我们将介绍这些方向的最新研究成果。
1、图像处理
自从卷积神经网络(CNN)掀起了深度学习革命,计算机视觉领域一直被卷积神经网络牢牢占据。最近,Transformer模型也被应用于这一领域,并取得了喜人的效果,几乎能与CNN平分秋色,下面我们来看几个例子。
iGPT
M. Chen et al., “Generative Pretraining from Pixels,”Proceedings of the 37th International Conferenceon Machine Learning 119(2020):1691-1703,https://proceedings.mlr.press/v119/chen20s.html.
受到GPT模型在文本处理领域大获成功的启发,iGPT(image GPT)将同样的方法应用于图像处理。通过将图像视为像素序列,iGPT沿用GPT的架构和自回归预训练目标来预测下一个像素值。经过大型图像数据集预训练的iGPT能够“自动填充”图像的部分内容,如下图所示。当分类头被添加到模型中时,iGPT还能在分类任务中获得不错的效果。
ViT
A. Dosovitskiy et al., “An Image Is Worth 16x16 Words: Transformersfor Image Recognition at Scale”(https://arxiv.org/abs/2010.11929),(2020).
从iGPT的介绍中可以获知,iGPT严格按照GPT架构风格与预训练方式,而ViT(Vision Transformer) 是一个依照BERT风格的用于视觉领域的Transformer模型,如下图所示。它的原理是先将图像分割成为较小的图像块,再通过线性投影进行向量化。处理过程非常类似BERT模型对词元的向量化。而后面的处理也几乎相同,将图像块向量和位置向量相结合,再提交给Transformer的编码器。在预训练过程中,一些图像块被掩码或扭曲,目的是预测被掩码的图像块的平均色彩。
虽然这种方法在标准的ImageNet数据集上进行预训练时并没有取得多么好的效果,但在更大的数据集上,其扩展性明显优于CNN。
ViT被集成到Hugging Face Transformers库中,它的使用方式与本书介绍的NLP pipeline的使用方式很相似,下面从加载那只著名的柴犬图片开始:
# 导入Python Imaging Library(PIL)库中的Image模块,用于图像处理
from PIL import Image
# 导入matplotlib库中的pyplot模块,用于绘图和显示图像
import matplotlib.pyplot as plt
# 使用Image.open()函数打开一个图像文件,文件名为"images/doge.jpg"
image = Image.open("images/doge.jpg")
# 使用matplotlib的imshow()函数显示图像,这里将image变量作为函数参数传入
plt.imshow(image)
# 使用plt.axis("off")关闭图像的坐标轴显示,使得图像显示更为简洁
plt.axis("off")
# 使用plt.show()函数显示图像,这将打开一个窗口展示图像
plt.show()
运行结果:
要加载一个ViT模型,只需指定image-classification pipeline即可,然后输入图像来提取预测出的类别:
# 导入pandas库,并将其简称为pd,pandas是一个强大的数据分析和操作库
import pandas as pd
# 从transformers库中导入pipeline函数,transformers是一个用于自然语言处理的库
from transformers import pipeline
# 使用pipeline函数创建一个图像分类器,"image-classification"是预设的任务类型
image_classifier = pipeline("image-classification")
# 调用image_classifier的预测方法,传入待分类的图像,这里的'image'应该是之前定义的图像变量
preds = image_classifier(image)
# 使用pandas的DataFrame构造函数将预测结果转换为DataFrame格式,便于进一步的数据处理和分析
preds_df = pd.DataFrame(preds)
# 最后一行代码preds_df,通常用于打印或返回DataFrame对象,以便查看预测结果
preds_df
运行结果:
结果显示预测结果非常准确!
G. Bertasius, H. Wang, and L. Torresani, “Is Space-Time Attention All You Need for Video Understanding?”(https://arxiv.org/abs/2102.05095), (2021).
谈到图像处理模型很自然就能延伸到视频处理模型,但视频除了空间维度之外还有时间维度,这会使任务更具有挑战性,因为需要处理的数据量更大。于是TimeSformer这样的模型就引入了一个空间和时间注意力机制来处理这些问题。在未来,这类模型可以帮助人们构建用途更加广泛的应用,比如视频序列的分类或者标注。
2、表格处理
很多数据,比如公司内部的客户关系数据,都存储在结构化的数据库中,而不是作为原始文本。我们在第7章中介绍过,通过问答模型可以用问题来查询答案文本。如果能像图中所示的那样,岂不是更好?
J. Herzig et al., “TAPAS: Weakly Supervised Table Parsing via Pre-Training”(https://arxiv.org/abs/2004.02349),(2020).
TAPAS(Table Parse)的出现,让我们能将Transformer模型架构应用于表格。该模型将表格的信息与查询相结合,如下图所示。
下面我们来看看TAPAS在实际应用中是如何工作的,借助一个案例,我们创建了本书(英文原书)目录的虚构版本,包含章节编号、章节名称以及章节起始、结束页码:
# 创建一个名为book_data的列表,用于存储书籍的章节数据
book_data = [
# 第一个字典,表示书籍的引言部分
{"chapter": 0, "name": "Introduction", "start_page": 1, "end_page": 11},
# 第二个字典,表示书籍的第一章,关于文本分类
{"chapter": 1, "name": "Text classification", "start_page": 12, "end_page": 48},
# 第三个字典,表示书籍的第二章,关于命名实体识别
{"chapter": 2, "name": "Named Entity Recognition", "start_page": 49, "end_page": 73},
# 第四个字典,表示书籍的第三章,关于问答系统
{"chapter": 3, "name": "Question Answering", "start_page": 74, "end_page": 120},
# 第五个字典,表示书籍的第四章,关于文本摘要
{"chapter": 4, "name": "Summarization", "start_page": 121, "end_page": 140},
# 第六个字典,表示书籍的结论部分
{"chapter": 5, "name": "Conclusion", "start_page": 141, "end_page": 144}
# 每个字典都包含章节编号、章节名称、起始页码和结束页码
]
我们也可以用现有的字段轻松地为每章添加页数。为了与TAPAS模型更好地配合,需要确保所有的列都是str类型:
# 导入pandas库,并将其简称为pd,pandas是一个用于数据分析和操作的强大库
import pandas as pd
# 将之前定义的书籍章节数据book_data转换为pandas的DataFrame对象,便于进行数据分析和操作
table = pd.DataFrame(book_data)
# 计算每个章节的页数,并将其存储在新的列'number_of_pages'中
# 这里通过'end_page'减去'start_page'来计算每个章节的页数
table['number_of_pages'] = table['end_page'] - table['start_page']
# 将DataFrame中所有的数据类型转换为字符串类型
# 这样做可以确保在后续处理中,数据类型一致,避免类型相关的错误
table = table.astype(str)
# 最后打印或返回table对象,以便查看DataFrame的内容
# 这通常在Jupyter Notebook或其他支持DataFrame显示的环境中使用
table
运行结果:
chapter name start_page end_page number_of_pages 0 0 Introduction 1 11 10 1 1 Text classification 12 48 36 2 2 Named Entity Recognition 49 73 24 3 3 Question Answering 74 120 46 4 4 Summarization 121 140 19 5 5 Conclusion 141 144 3
现在我们知道了这个操作步骤了,下面我们来加载table-question-answeringpipeline:
# 从transformers库中导入pipeline函数
from transformers import pipeline
# 使用pipeline函数创建一个表格问答(table-question-answering)模型
# 这个模型能够根据表格数据和问题生成答案
table_qa = pipeline("table-question-answering")
(注意:如果没有安装 torch-scatter,在 Jupyter notebook 中使用 !pip install torch-scatter 进行安装)
然后通过一些查询问题来提取答案:
# 从transformers库中导入pipeline函数
from transformers import pipeline
# 使用pipeline函数创建一个表格问答模型,该模型能够回答关于表格数据的问题
table_qa = pipeline("table-question-answering")
# 定义一系列问题,这些问题将被用来询问表格数据
# 问题包括关于章节主题、总页数、特定章节的起始页码以及页数超过20的章节数量
queries = [
"What's the topic in chapter 4?", # 询问第四章的主题
"What is the total number of pages?", # 询问书籍的总页数
"On which page does the chapter about question-answering start?", # 询问关于问答系统的章节起始页码
"How many chapters have more than 20 pages?" # 询问有多少章节的页数超过20
]
# 使用table_qa模型回答上述问题,传入表格数据table和问题列表queries
# 这将返回每个问题的答案
preds = table_qa(table, queries)
这些预测将表的操作类型和答案一起封装在aggregator字段中,下面看看TAPAS模型在我们的问题上实际效果如何:
# 使用zip函数将queries列表和preds列表的元素配对,这样我们可以同时遍历问题和它们的答案
for query, pred in zip(queries, preds):
# 打印当前的问题
print(query)
# 检查pred字典中的"aggregator"键对应的值是否为"NONE"
# "aggregator"可能表示在生成答案时是否使用了某种聚合操作,如求和、平均等
# 在此代码段中,"aggregator"的值似乎并不影响输出,因为无论它的值是什么,答案都以相同的方式打印
if pred["aggregator"] == "NONE":
# 如果没有使用聚合操作,打印出预测的答案
print("Predicted answer: " + pred["answer"])
else:
# 如果使用了某种聚合操作,同样打印出预测的答案
# 注意:这里的else分支可能是多余的,因为不管aggregator的值是什么,答案都打印了
print("Predicted answer: " + pred["answer"])
# 打印一个由50个等号组成的分隔线,用于视觉上分隔不同的问题和答案
print('='*50)
运行结果:
What's the topic in chapter 4? Predicted answer: Summarization ================================================== What is the total number of pages? Predicted answer: SUM > 10, 36, 24, 46, 19, 3 ================================================== On which page does the chapter about question-answering start? Predicted answer: AVERAGE > 74 ================================================== How many chapters have more than 20 pages? Predicted answer: COUNT > 1, 2, 3 ==================================================
从结果可以看出,四个问题均得到了正确的答案,当然也可以使用Pandas来解决,但是拥有一个能理解语义并给出答案的工具,就可以做更多的事。
四、多模态的Transformer
到目前为止,我们已经介绍了将Transformer扩展到其他单一模态的方法。可能很多人会将TAPAS看做是多模态的,因为它结合了文本和表格,但其实表格也被当成了文本来处理。在本节中,我们将为大家介绍如何将Transformer应用在多模态的解决方案中,比如音频结合文本或者图像结合文本。
1、语音和文本处理
虽然将计算机与文本对接起来是工业界一个巨大的进步,但我们日常生活中更自然的沟通方式依然是使用语音交流。现在像Siri或Alexa这样的应用程序越来越多,并且成为一种趋势。另外,对于很大一部分人来说,写作与阅读比进行语音交流更具备挑战性。因此,语音识别与理解就显得很有必要了,可以帮助到许多人。这个领域的一个常见任务是自动语音识别(Automatic Speech Recognition,ASR),它可以将语音转换为文本,然后使用NLP技术处理文本,这样就能像Siri那样回答很多问题。
A. Baevski et al., “wav2vec 2.0: A Framework for Self-Supervised Learning of Speech Representations”(https://arxiv.org/abs/2006.11477),(2020).
目前,wav2wav 2.0(https://oreil.ly/tPpC7)系列模型是自动语音识别领域的最新技术之一:它们使用Transformer与CNN相结合,如下图所示。通过在预训练期间利用未标注的数据,这些模型只需要几分钟的语料就可以获得理想效果。
wav2wav 2.0模型也被集成到了Hugging Face Transformers库之中,可以使用之前熟悉的步骤来加载它。下面来加载一个预训练模型,此模型已经进行了960h的语音数据的训练:
# 从transformers库中导入pipeline函数,这是一个便捷工具,用于快速加载预训练模型
from transformers import pipeline
# 使用pipeline函数创建一个自动语音识别(automatic-speech-recognition, ASR)模型
# 这个模型能够将音频输入转换成文本输出,广泛应用于语音到文本的转换任务
asr = pipeline("automatic-speech-recognition")
运行结果:
为了将此模型应用于一些音频文件,我们将使用SUPERB数据集(https://oreil.ly/iBAK8)的ASR子集,这也是该模型预训练使用的数据集。由于该数据集相当庞大,这里只加载一个案例用于演示:
# 从datasets库中导入load_dataset函数,这是Hugging Face datasets库的一部分
# 该库提供了一个统一的API来加载和处理各种公共数据集
from datasets import load_dataset
# 使用load_dataset函数加载名为"superb"的数据集,具体是其中的"asr"配置
# 这里指定了split参数为"validation[:1]",意味着我们只加载验证集的第一条数据记录
ds = load_dataset("superb", "asr", split="validation[:1]")
# 打印加载的数据集的第一条记录,这通常用于检查数据是否正确加载
print(ds[0])
(注意:如果没有安装 soundfile ,在 Jupyter notebook 中使用 !pip install soundfile 进行安装)
(注意:如果没有安装 librosa ,在 Jupyter notebook 中使用 !pip install librosa 进行安装)
运行结果:
{'file': 'C:/Users/xiankui.qin/.cache/huggingface/datasets/downloads/extracted/d98b36e753b5b330f5f2b21e4a143e3dce5fa896a76f09ece08ca932cef25d88/LibriSpeech/dev-clean/1272/128104\\1272-128104-0000.flac', 'audio': {'path': 'C:/Users/xiankui.qin/.cache/huggingface/datasets/downloads/extracted/d98b36e753b5b330f5f2b21e4a143e3dce5fa896a76f09ece08ca932cef25d88/LibriSpeech/dev-clean/1272/128104\\1272-128104-0000.flac', 'array': array([0.00238037, 0.0020752 , 0.00198364, ..., 0.00042725, 0.00057983, 0.0010376 ]), 'sampling_rate': 16000}, 'text': 'MISTER QUILTER IS THE APOSTLE OF THE MIDDLE CLASSES AND WE ARE GLAD TO WELCOME HIS GOSPEL', 'speaker_id': 1272, 'chapter_id': 128104, 'id': '1272-128104-0000'}
这里我们可以看到,文件中的音频是以FLAC格式存储的,识别出的内容则在text字段。为了将音频转换为浮点数组,可以使用SoundFile库(https://oreil.ly/eo106),再用map()函数读取数据集中的每个文件:
# 导入soundfile库,这是一个用于读取和写入声音文件的库
import soundfile as sf
# 定义一个函数map_to_array,该函数将用于将数据集中的每个元素(batch)映射到包含音频数组的形式
def map_to_array(batch):
# 使用soundfile的read函数读取batch中的音频文件,并将音频数据存储到变量speech中
# _ 表示我们不使用read函数返回的第二个值,即文件的元数据
speech, _ = sf.read(batch["file"])
# 将读取的音频数据添加到batch字典中,键为"speech"
batch["speech"] = speech
# 返回更新后的batch
return batch
# 使用map函数将map_to_array应用到数据集ds的每个元素上
# 这将转换数据集中的每个元素,为它们添加一个包含音频数组的"speech"键
ds = ds.map(map_to_array)
运行结果:
如果你使用的是Jupyter notebook,则可以利用下面的IPython小工具来播放语音文件:
# 从IPython.display模块导入Audio类,这个类用于在Jupyter Notebook中显示音频
from IPython.display import Audio
# 调用display函数来展示数据集ds中第一条记录的音频
# 这里使用了Audio类来创建一个音频显示对象,其中ds[0]['speech']是音频数据
# rate=16000指定了音频的采样率,这里假设音频的采样率为16000Hz
# 这行代码通常用在Jupyter Notebook环境中,可以直接播放音频文件
display(Audio(ds[0]['speech'], rate=16000))
运行结果:
最后,将输入传给pipeline,获取识别结果:
# 使用set_format方法将数据集ds的数据格式设置为"numpy"
# 这通常是为了确保数据集的元素可以以NumPy数组的形式被处理,这对于某些模型输入是必需的
ds.set_format(type="numpy", columns=["speech"])
# 使用之前创建的自动语音识别模型asr对数据集中第一条记录的音频数据进行预测
# 这里假设asr模型已经正确初始化,并且ds[0]["speech"]包含了音频数据
pred = asr(ds[0]["speech"])
# 打印预测结果pred,这将展示ASR模型对音频数据的识别结果
print(pred)
运行结果:
{'text': 'MISTER QUILTER IS THE APOSTLE OF THE MIDDLE CLASSES AND WE ARE GLAD TO WELCOME HIS GOSPEL'}
通过区区几行代码,我们就构建了一个语音识别应用程序。这个识别结果看起来是正确的,但缺少标点符号,可以在后期的处理步骤中添加处理逻辑。
A. Baevski et al., “Unsupervised Speech Recognition”(https://arxiv.org/abs/2105.11084),(2021).
为一种语言构建语音识别模型需要相当多的标注数据,获取这种高保真的数据以及数据标注要耗费不少成本,特别是那种低资源语言。在wav2wav 2.0发布后不久,一篇介绍wav2vec-U方法的论文被发表。它是一种无监督的方法,只需要从未标注语音和未标注的文本数据中进行学习,无须进行任何转录,原理如图11-13所示。它适用于任何语言或者方言的语音识别。
所以Transformer模型也可以同时具备处理语音和文本的能力。最新的研究不止如此,它还具备同时进行图形处理的能力,这也是目前最前沿的研究领域之一。
2、图像和文、本处理
图像与文本结合处理又是另一种多模态结合形式,在日常生活中,我们也时常会从图像和视频中提取并处理有关内容。除了将Transformer单纯用于处理图像之外,结合文本处理也取得了一定的进展。在本节中,我们将介绍处理图像与文本双模态的四个实践:VisualQA、LayoutLM、DALL·E和CLIP。
- VQA
. Goyal et al., “Making the V in VQA Matter:Elevating the Role of Image Understanding in Visual Question Answering”(https://arxiv.org/abs/1612.00837),(2016).
在之前介绍中,我们介绍了如何使用Transformer模型来从文本中提取问答对,处理方式包括在线处理和离线处理,这里的问答模型用于从一组文档中提取结构化信息。最新的研究已经将它扩展到了视觉领域,例如如下图所示的VQA等数据集。
H. Tan and M. Bansal,“LXMERT: Learning Cross-Modality Encoder Representations from Transformers”(https://arxiv.org/abs/1908.07490),(2019);L.H. Li et al., “VisualBERT:A Simple and Performant Baseline for Vision and Language”(https://arxiv.org/abs/1908.03557),(2019).
像LXMERT和VisualBERT这样的模型使用ResNets等视觉模型从图像中提取特征,然后利用Transformer的编码器将其与自然问题结合并预测出答案。
- LayoutLM
单据、发票或者报告识别等业务在很多公司都需要,这也是另一个研究领域,业内常使用提取文本或者布局信息等手段来处理。在这个领域中,LayoutLM(https://oreil.ly/uQc5t)系列模型是目前最先进的。它们运用一个增强Transformer架构,接收三个模态的输入信息:文本、图像和布局。因此,如下图所示,每个模态都有与之对应的嵌入层,一个空间感知的自我关注机制,以及一个将图像与文本混合的预训练目标。通过数以百万计的扫描文件进行预训练,LayoutLM模型能够以类似NLP领域BERT模型的方式转移到各种下游任务中。
- DALL·E
A. Ramesh et al., “Zero-Shot Text-to-Image Generation”(https://arxiv.org/abs/2102.12092),(2021).
DALL·E 是一个结合了图像和文本生成能力的模型。它使用GPT模型架构和自回归建模方式来从文本中生成图像。受iGPT模型的启发,它将文字和像素视为一个词元序列,因此能够从文本提示中生成图像,如下图所示。
CLIP
A. Radford et al., “Learning Transferable Visual Models from Natural Language Supervision”(https://arxiv.org/abs/2103.00020),(2021).
最后,我们来看看CLIP,它也将文本和图像结合处理,专为监督任务设计。它的创造者构建了一个有4亿图像与对应图像描述的数据集,并使用对比学习来预训练模型。CLIP的架构包括一个文本和一个图像编码器(都是Transformer),构建了图像和描述的向量。将一批带有描述的图像采样,对比性目标是使相应的一对向量的相似度最大(由点积来度量),同时让其他向量的相似度最小,如图所示。
为了用预训练的模型进行分类,一些可能的类被加入文本编码器中,类似于我们使用零样本pipeline的方式。然后我们将所有类的向量与我们想要的图像向量进行比较,选择相似度最高的类。
CLIP的零样本图像分类性能不错,几乎能与完全监督训练出的视觉模型相媲美,并且能够在新类别的识别方面具备更好的灵活性。CLIP也被集成到了Hugging Face Transformers库当中,我们可以直接使用它。对于从图像中提取文本的任务,这里实例化了一个processor,由一个特征提取器和词元分析器组成。特征提取器的作用是将图像转换成适合于模型的形式,而词元分析器负责将模型的预测解码成文本。
# 从transformers库中导入CLIPProcessor和CLIPModel类
from transformers import CLIPProcessor, CLIPModel
# 指定要使用的CLIP模型的名称,这里使用的是openai提供的预训练模型
# "openai/clip-vit-base-patch32"是一个基于Vision Transformer的CLIP模型
clip_ckpt = "openai/clip-vit-base-patch32"
# 使用CLIPModel类的from_pretrained方法加载预训练的CLIP模型
# 这将下载模型权重并初始化模型,以便进行图像和文本的多模态处理
model = CLIPModel.from_pretrained(clip_ckpt)
# 使用CLIPProcessor类的from_pretrained方法加载与模型对应的处理工具
# 处理器负责将输入数据(如图像和文本)转换为模型能够理解的格式
processor = CLIPProcessor.from_pretrained(clip_ckpt)
运行结果:
这里我们使用擎天柱的图片来测试:
# 导入PIL库中的Image模块,这是一个用于图像处理的库
from PIL import Image
# 导入matplotlib库中的pyplot模块,这是一个用于绘图的库
import matplotlib.pyplot as plt
# 使用Image.open()函数打开一个图像文件,文件路径为"images/optimusprime.jpg"
# 这个函数会读取图像文件并返回一个Image对象
image = Image.open("images/optimusprime.jpg")
# 使用matplotlib的imshow()函数在图像窗口中显示图像对象
# 这里将image对象作为参数传递给imshow()函数
plt.imshow(image)
# 使用plt.axis("off")关闭图像显示中的坐标轴,使图像显示更加简洁
plt.axis("off")
# 使用plt.show()函数显示图像,这将打开一个窗口展示图像
# 这个函数通常用于Jupyter Notebook或其他支持matplotlib显示的环境中
plt.show()
运行结果:
接下来,设置描述文本,与图像进行比较,并传给模型:
# 导入PyTorch库,这是一个开源的机器学习库,广泛用于深度学习任务
import torch
# 定义一个文本列表,包含与图像相关的描述
texts = ["a photo of a transformer", "a photo of a robot", "a photo of agi"]
# 使用之前创建的CLIPProcessor的processor方法来处理文本和图像输入
# 这里将texts和images作为参数传递给processor方法
# return_tensors="pt"指示处理器返回PyTorch张量
# padding=True表示对文本序列进行填充,以确保它们的长度一致
inputs = processor(text=texts, images=image, return_tensors="pt", padding=True)
# 使用with语句创建一个torch.no_grad()上下文,这将关闭梯度计算
# 这在推理阶段很有用,可以减少内存消耗和提高计算速度
with torch.no_grad():
# 调用CLIPModel的model方法进行推理,将处理后的输入传递给模型
# **表示将inputs字典解包为关键字参数
outputs = model(**inputs)
# 从模型的输出中获取每个图像的logits(即模型的原始输出)
logits_per_image = outputs.logits_per_image
# 使用softmax函数对logits进行归一化处理,得到每个类别的概率
# dim=1表示沿着张量的第二维(通常是类别维度)应用softmax
probs = logits_per_image.softmax(dim=1)
# 最后打印概率张量probs,这将展示模型对每个文本描述的分类概率
probs
运行结果:
tensor([[0.9515, 0.0443, 0.0041]])
最后得到了正确的答案,CLIP使图像分类非常灵活,它允许通过文本定义类,而不是在模型架构中硬编码类。
3、继续前行的建议
好了,这就是我们带你穿越Transformer领域的全部旅程!在本书中,我们探讨了Transformers如何应对各种任务并取得最先进的结果。在这里,我们看到了当前的模型是如何通过扩大规模和拓展新领域和模态性能够推动其极限的。
如果你想加强本书中所学习的概念和技能,以下是一些继续前行的建议:
- 参加Hugging Face社区活动
Hugging Face举办了短期冲刺活动,专注于改善生态系统中的库,这些活动是认识社区和尝试开源软件开发的绝佳方式。迄今为止,这里已经有关于向Hugging Face Datasets添加600多个数据集、在多种语言中微调300多个ASR模型,以及在JAX/Flax中实现数百个项目的冲刺活动。
- 构建自己的项目
测试机器学习知识的一种有效方法是构建一个解决你感兴趣的问题的项目。你可以重新创作一篇Transformer论文,或将Transformer应用于新领域。
- 向Hugging Face Transformers库贡献模型
如果你正在寻找更高级的东西,那么向Hugging Face Transformers库贡献新发布的架构是深入了解库的细节的好方法。Hugging Face Transformers库文档中有一份详细的指南,可以帮助你开始(https://oreil.ly/3f4wZ)。
- 写博客记录所学
向他人教授你所学习到的知识是考验自己知识的一个强有力的测试,在某种意义上,这正是我们写作本书的主要动力之一!有很多优秀的工具可以帮助你开始技术博客。我们推荐fastpages(https://oreil.ly/f0L9u),因为你可以轻松使用Jupyter notebook来完成其中的所有内容。
附录
一、当前案例环境 package 的 版本如下
Package Version
------------------------- --------------
absl-py 2.1.0
accelerate 0.32.1
aiohttp 3.9.5
aiosignal 1.3.1
alembic 1.13.2
anyio 4.4.0
argon2-cffi 23.1.0
argon2-cffi-bindings 21.2.0
arrow 1.3.0
asttokens 2.4.1
async-lru 2.0.4
attrs 23.2.0
audioread 3.0.1
Babel 2.15.0
beautifulsoup4 4.12.3
bleach 6.1.0
certifi 2024.7.4
cffi 1.16.0
charset-normalizer 3.3.2
click 8.1.7
colorama 0.4.6
coloredlogs 15.0.1
colorlog 6.8.2
comm 0.2.2
contourpy 1.2.1
cycler 0.12.1
datasets 2.20.0
debugpy 1.8.2
decorator 5.1.1
defusedxml 0.7.1
dill 0.3.8
docker-pycreds 0.4.0
executing 2.0.1
faiss-cpu 1.8.0.post1
fastjsonschema 2.20.0
filelock 3.15.4
flatbuffers 24.3.25
fonttools 4.53.1
fqdn 1.5.1
frozenlist 1.4.1
fsspec 2024.5.0
gdown 5.2.0
gitdb 4.0.11
GitPython 3.1.43
greenlet 3.0.3
grpcio 1.65.1
h11 0.14.0
httpcore 1.0.5
httpx 0.27.0
huggingface-hub 0.23.4
humanfriendly 10.0
idna 3.7
intel-openmp 2021.4.0
ipykernel 6.29.5
ipython 8.26.0
ipywidgets 8.1.3
isoduration 20.11.0
jedi 0.19.1
Jinja2 3.1.4
joblib 1.4.2
json5 0.9.25
jsonpointer 3.0.0
jsonschema 4.23.0
jsonschema-specifications 2023.12.1
jupyter 1.0.0
jupyter_client 8.6.2
jupyter-console 6.6.3
jupyter_core 5.7.2
jupyter-events 0.10.0
jupyter-lsp 2.2.5
jupyter_server 2.14.2
jupyter_server_terminals 0.5.3
jupyterlab 4.2.3
jupyterlab_pygments 0.3.0
jupyterlab_server 2.27.2
jupyterlab_widgets 3.0.11
kiwisolver 1.4.5
lazy_loader 0.4
librosa 0.10.2.post1
llvmlite 0.43.0
Mako 1.3.5
Markdown 3.6
MarkupSafe 2.1.5
matplotlib 3.9.1
matplotlib-inline 0.1.7
mistune 3.0.2
mkl 2021.4.0
mpmath 1.3.0
msgpack 1.0.8
multidict 6.0.5
multiprocess 0.70.16
nbclient 0.10.0
nbconvert 7.16.4
nbformat 5.10.4
nest-asyncio 1.6.0
networkx 3.3
nlpaug 1.1.11
notebook 7.2.1
notebook_shim 0.2.4
numba 0.60.0
numpy 1.26.4
onnx 1.16.1
onnxruntime 1.18.1
optuna 3.6.1
overrides 7.7.0
packaging 24.1
pandas 2.2.2
pandocfilters 1.5.1
parso 0.8.4
pillow 10.4.0
pip 24.1.2
platformdirs 4.2.2
pooch 1.8.2
prometheus_client 0.20.0
prompt_toolkit 3.0.47
protobuf 4.25.3
psutil 6.0.0
pure-eval 0.2.2
pyarrow 16.1.0
pyarrow-hotfix 0.6
pycparser 2.22
Pygments 2.18.0
pyparsing 3.1.2
pyreadline3 3.4.1
PySocks 1.7.1
python-dateutil 2.9.0.post0
python-json-logger 2.0.7
pytz 2024.1
pywin32 306
pywinpty 2.0.13
PyYAML 6.0.1
pyzmq 26.0.3
qtconsole 5.5.2
QtPy 2.4.1
referencing 0.35.1
regex 2024.5.15
requests 2.32.3
rfc3339-validator 0.1.4
rfc3986-validator 0.1.1
rpds-py 0.19.0
safetensors 0.4.3
scikit-learn 1.5.1
scikit-multilearn 0.2.0
scipy 1.14.0
Send2Trash 1.8.3
sentencepiece 0.2.0
sentry-sdk 2.10.0
setproctitle 1.3.3
setuptools 70.0.0
six 1.16.0
smmap 5.0.1
sniffio 1.3.1
soundfile 0.12.1
soupsieve 2.5
soxr 0.3.7
SQLAlchemy 2.0.31
stack-data 0.6.3
sympy 1.13.0
tbb 2021.13.0
tensorboard 2.17.0
tensorboard-data-server 0.7.2
terminado 0.18.1
threadpoolctl 3.5.0
tinycss2 1.3.0
tokenizers 0.13.3
torch 2.3.1+cu121
torch_scatter 2.1.2
torchaudio 2.3.1+cu121
torchvision 0.18.1+cu121
tornado 6.4.1
tqdm 4.66.4
traitlets 5.14.3
transformers 4.24.0
types-python-dateutil 2.9.0.20240316
typing_extensions 4.12.2
tzdata 2024.1
uri-template 1.3.0
urllib3 2.2.2
wandb 0.17.5
wcwidth 0.2.13
webcolors 24.6.0
webencodings 0.5.1
websocket-client 1.8.0
Werkzeug 3.0.3
wheel 0.43.0
widgetsnbextension 4.0.11
xxhash 3.4.1
yarl 1.9.4