Transformers 自然语言处理(五)(1)https://developer.aliyun.com/article/1514247
代码中的视觉变换器
在本节中,我们将重点关注与视觉变换器特定体系结构相关的主要代码区域。
打开Vision_Transformers.ipynb
,它位于本章的 GitHub 存储库中。
Google Colab VM 中包含许多预安装的软件包,如torch
和torchvision
。可以通过在笔记本的第一个单元格中取消注释该命令来显示它们:
#Uncomment the following command to display the list of pre-installed modules #!pip list -v
然后前往笔记本的Vision Transformer(ViT)单元。该笔记本先安装了 Hugging Face transformers 并导入了必要的模块:
!pip install transformers from transformers import ViTFeatureExtractor, ViTForImageClassification from PIL import Image import requests
注意:在撰写本书时,Hugging Face 警告我们,由于不断的演变,代码可能不稳定。但这不应阻止我们探索 ViT 模型。探索新领域正是前沿的所在!
然后我们从 COCO 数据集下载了一幅图像。如果你想进一步进行实验,可以在他们的网站上找到大量数据集:cocodataset.org/
让我们从 VAL2017 数据集中下载。按照 COCO 数据集网站的说明通过程序获取这些图像或在本地下载数据集。
VAL2017 包含了 5,000 张我们可以选择的图像,以测试这个 ViT 模型。你可以运行其中任何一张图像。
让我们用猫的图片测试笔记本。我们首先通过它们的 URL 检索猫的图片:
url = 'http://images.cocodataset.org/val2017/000000039769.jpg' image = Image.open(requests.get(url, stream=True).raw)
我们接下来要下载 Google 的特征提取器和分类模型:
feature_extractor = ViTFeatureExtractor.from_pretrained('google/vit-base-patch16-224') model = ViTForImageClassification.from_pretrained('google/vit-base-patch16-224')
该模型在 224 x 244 分辨率图像上进行训练,但在特征提取和分类时采用了 16 x 16 的块。笔记本运行模型并进行预测:
inputs = feature_extractor(images=image, return_tensors="pt") outputs = model(**inputs) logits = outputs.logits # model predicts one of the 1000 ImageNet classes predicted_class_idx = logits.argmax(-1).item() print("Predicted class:",predicted_class_idx,": ", model.config.id2label[predicted_class_idx])
输出为:
Predicted class: 285 : Egyptian cat
探索在预测后的代码,它提供了一些低层次的信息,其中包括:
model.config.id2label
,会列出类的标签。这 1000 个标签类解释了为什么我们得到一个类而不是详细的文本描述:
{0: 'tench, Tinca tinca',1: 'goldfish, Carassius auratus', 2: 'great white shark, white shark, man-eater, man-eating shark, Carcharodon carcharias',3: 'tiger shark, Galeocerdo cuvieri',...,999: 'toilet tissue, toilet paper, bathroom tissue'}
模型
,该模型将显示从卷积输入子层开始的模型架构:
(embeddings): ViTEmbeddings( (patch_embeddings): PatchEmbeddings( (projection): Conv2d(3, 768, kernel_size=(16, 16), stride=(16, 16)) )
在卷积输入嵌入子层之后,模型是一个类似 BERT 的编码器。
请花些时间探索这个创新的从 NLP 变换器到图像变换器的转变,迅速导向为一切都使用变换器。
现在,让我们了解另一个计算机视觉模型 CLIP。
CLIP
对比语言-图像预训练(CLIP)遵循了变换器的理念。它在其变换器类型的层中插入数据序列。这次,模型发送的是文本-图像对,而不是文本对。一旦数据被分词、编码和嵌入,CLIP,一个无关任务的模型,就像处理任何其他数据序列一样学习文本-图像对。
这种方法是对比的,因为它寻找图像特征中的对比。这是我们在一些杂志游戏中使用的方法,在这些游戏中,我们必须找到两幅图像之间的差异,对比。
让我们先看一下 CLIP 的架构,然后再看代码。
CLIP 的基本架构
对比:图像通过它们的差异和相似之处学习如何相互配合。通过(联合文本,图像)预训练,图像和字幕找到彼此的路径。预训练后,CLIP 学习新任务。
CLIP 是可转移的,因为它们可以学习新的视觉概念,就像 GPT 模型一样,比如视频序列中的动作识别。字幕带来了无尽的应用。
ViT 将图像分割成类似单词的补丁。CLIP 联合训练文本和图像编码器以最大化余弦相似度,如图 15.11所示:
图 15.11:联合训练文本和图像
图 15.11显示了Transformers将为文本输入运行标准Transformers编码器。它将在Transformers结构中为图像运行一个 ResNet 50 层 CNN。 ResNet 50 被修改为在具有多头 QKV 注意头的注意力池化机制中运行平均池化层。
让我们看看 CLIP 是如何学习文本-图像序列以进行预测的。
代码中的 CLIP
打开 GitHub 上本章的存储库中的Vision_Transformers.ipynb
。然后转到笔记本的CLIP
单元格。
该程序开始安装 PyTorch 和 CLIP:
!pip install ftfy regex tqdm !pip install git+https://github.com/openai/CLIP.git
该程序还导入模块和 CIFAR-100 来访问图像:
import os import clip import torch from torchvision.datasets import CIFAR100
有 10,000 张图像可用,索引介于 0 和 9,999 之间。下一步是选择我们要进行预测的图像:
图 15.12:选择一个图像索引
程序然后将模型加载到可用的设备上(GPU 或 CPU):
# Load the model device = "cuda" if torch.cuda.is_available() else "cpu" model, preprocess = clip.load('ViT-B/32', device)
图像已下载:
# Download the dataset cifar100 = CIFAR100(root=os.path.expanduser("~/.cache"), download=True, train=False)
输入已准备好:
# Prepare the inputs image, class_id = cifar100[index] image_input = preprocess(image).unsqueeze(0).to(device) text_inputs = torch.cat([clip.tokenize(f"a photo of a {c}") for c in cifar100.classes]).to(device)
在运行预测之前,让我们可视化所选的输入:
import matplotlib.pyplot as plt from torchvision import transforms plt.imshow(image)
输出显示索引 15
是一只狮子:
图 15.13:索引 15 的图像
本节中的图像来自于从小图像中学习多层特征,Alex Krizhevsky,2009 年:www.cs.toronto.edu/~kriz/learning-features-2009-TR.pdf
。它们是CIFAR-10
和CIFAR-100
数据集的一部分(toronto.edu
):www.cs.toronto.edu/~kriz/cifar.html
我们知道这是一只狮子,因为我们是人类。一个最初设计用于自然语言处理的Transformers必须学习图像是什么。现在我们将看到它能多好地识别图像。
在计算特征时,程序表明正在运行一个联合Transformers模型,将图像输入与文本输入分开:
# Calculate features with torch.no_grad(): image_features = model.encode_image(image_input) text_features = model.encode_text(text_inputs)
现在 CLIP 进行预测并显示前五个预测:
# Pick the top 5 most similar labels for the image image_features /= image_features.norm(dim=-1, keepdim=True) text_features /= text_features.norm(dim=-1, keepdim=True) similarity = (100.0 * image_features @ text_features.T).softmax(dim=-1) values, indices = similarity[0].topk(5) # Print the result print("\nTop predictions:\n") for value, index in zip(values, indices): print(f"{cifar100.classes[index]:>16s}: {100 * value.item():.2f}%")
如果您想获得更多或更少的预测结果,可以修改topk(5)
。显示前五个预测:
Top predictions: lion: 96.34% tiger: 1.04% camel: 0.28% lawn_mower: 0.26% leopard: 0.26%
CLIP 找到了狮子,这显示了Transformers架构的灵活性。
下一个单元格显示类别:
cifar100.classes
您可以浏览类别,看看只有一个标签的情况下,CLIP 的表现如何受限制。
[...,'kangaroo','keyboard','lamp','lawn_mower','leopard','lion', 'lizard', ...]
笔记本包含了其他几个单元格,描述了您可以探索的 CLIP 的架构和配置。
model
单元格特别有趣,因为您可以看到以类似于 ViT 模型的卷积嵌入开始,然后继续作为一个“标准”大小为 768 的Transformers,具有多头注意力的视觉编码器:
CLIP( (visual): VisionTransformer( (conv1): Conv2d(3, 768, kernel_size=(32, 32), stride=(32, 32), bias=False) (ln_pre): LayerNorm((768,), eps=1e-05, elementwise_affine=True) (transformer): Transformer( (resblocks): Sequential( (0): ResidualAttentionBlock( (attn): MultiheadAttention( (out_proj): NonDynamicallyQuantizableLinear(in_features=768, out_features=768, bias=True) ) (ln_1): LayerNorm((768,), eps=1e-05, elementwise_affine=True) (mlp): Sequential( (c_fc): Linear(in_features=768, out_features=3072, bias=True) (gelu): QuickGELU() (c_proj): Linear(in_features=3072, out_features=768, bias=True) ) (ln_2): LayerNorm((768,), eps=1e-05, elementwise_affine=True) )
model
单元格的另一个有趣之处是查看与图像编码器同时运行的大小为 512 的文本编码器:
(transformer): Transformer( (resblocks): Sequential( (0): ResidualAttentionBlock( (attn): MultiheadAttention( (out_proj): NonDynamicallyQuantizableLinear(in_features=512, out_features=512, bias=True) ) (ln_1): LayerNorm((512,), eps=1e-05, elementwise_affine=True) (mlp): Sequential( (c_fc): Linear(in_features=512, out_features=2048, bias=True) (gelu): QuickGELU() (c_proj): Linear(in_features=2048, out_features=512, bias=True) ) (ln_2): LayerNorm((512,), eps=1e-05, elementwise_affine=True) )
浏览描述架构、配置和参数的单元格,了解 CLIP 如何表示数据。
我们展示了任务无关的Transformers模型将图像文本对处理为文本文本对。我们可以将任务无关模型应用于音乐文本、声音文本、音乐图像以及任何类型的数据对。
现在我们将探讨另一个任务无关的Transformers模型 DALL-E,它可以处理图像和文本。
DALL-E
与 CLIP 一样,DALL-E 是一个任务无关的模型。CLIP 处理文本图像对。DALL-E 分别处理文本和图像令牌。DALL-E 的输入是一个包含 1,280 个令牌的文本和图像的单一流。256 个令牌用于文本,1,024 个令牌用于图像。DALL-E 是一个像 CLIP 一样的基础模型。
DALL-E 的命名来源于 萨尔瓦多·达利 和 Pixar 的 WALL-E。DALL-E 的使用方法是输入文本提示并生成图像。然而,DALL-E 必须先学会如何用文本生成图像。
DALL-E 是 GPT-3 的 120 亿参数版本。
该Transformers使用文本-图像对数据集从文本描述生成图像。
DALL-E 的基本架构
与 CLIP 不同,DALL-E 将最多 256 个 BPE 编码的文本令牌与 32×32 = 1,024 个图像令牌连接起来,如 图 15.14 所示:
图 15.14:DALL-E 将文本和图像输入连接起来
图 15.14 显示,这一次我们的猫图像与输入文本连接在一起。
DALL-E 有一个编码器和一个解码器堆栈,其构建了将卷积功能注入到Transformers模型中的混合架构。
让我们窥探一下代码,看看模型是如何工作的。
代码中的 DALL-E
在本节中,我们将看到 DALL-E 如何重构图像。
打开 Vision_Transformers.ipynb
。然后转到笔记本的 DALL-E
单元格。笔记本首先安装 OpenAI DALL-E:
!pip install DALL-E
笔记本下载图像并处理图像:
import io import os, sys import requests import PIL import torch import torchvision.transforms as T import torchvision.transforms.functional as TF from dall_e import map_pixels, unmap_pixels, load_model from IPython.display import display, display_markdown target_image_size = 256 def download_image(url): resp = requests.get(url) resp.raise_for_status() return PIL.Image.open(io.BytesIO(resp.content)) def preprocess(img): s = min(img.size) if s < target_image_size: raise ValueError(f'min dim for image {s} < {target_image_size}') r = target_image_size / s s = (round(r * img.size[1]), round(r * img.size[0])) img = TF.resize(img, s, interpolation=PIL.Image.LANCZOS) img = TF.center_crop(img, output_size=2 * [target_image_size]) img = torch.unsqueeze(T.ToTensor()(img), 0) return map_pixels(img)
程序现在加载 OpenAI DALL-E 编码器和解码器:
# This can be changed to a GPU, e.g. 'cuda:0'. dev = torch.device('cpu') # For faster load times, download these files locally and use the local paths instead. enc = load_model("https://cdn.openai.com/dall-e/encoder.pkl", dev) dec = load_model("https://cdn.openai.com/dall-e/decoder.pkl", dev)
我添加了 enc
和 dec
单元格,以便您可以查看编码器和解码器块,了解这种混合模型的工作原理:Transformers模型中的卷积功能和文本与图像输入的连接。
本节中处理的图像是 mycat.jpg
(作者:Denis Rothman,版权所有,需取得书面许可方可复制)。该图像位于本书存储库的 Chapter15
目录中。它已被下载并处理:
x=preprocess(download_image('https://github.com/Denis2054/AI_Educational/blob/master/mycat.jpg?raw=true'))
最后,我们显示原始图片:
display_markdown('Original image:') display(T.ToPILImage(mode='RGB')(x[0]))
输出显示图像:
图 15.15:一张猫的图片
现在,程序处理并显示重建图像:
import torch.nn.functional as F z_logits = enc(x) z = torch.argmax(z_logits, axis=1) z = F.one_hot(z, num_classes=enc.vocab_size).permute(0, 3, 1, 2).float() x_stats = dec(z).float() x_rec = unmap_pixels(torch.sigmoid(x_stats[:, :3])) x_rec = T.ToPILImage(mode='RGB')(x_rec[0]) display_markdown('Reconstructed image:') display(x_rec)
重建后的图像看起来与原始图像极为相似:
图 15.16:DALL-E 重建了猫的图像
结果令人印象深刻。DALL-E 学会了如何自动生成图像。
在书写本书时,完整的 DALL-E 源代码尚不可用,也许永远都不会。目前尚未上线 OpenAI 的 API,用于从文本提示生成图像。但请保持关注!
与此同时,我们可以继续在 OpenAI 上发现 DALL-E:openai.com/blog/dall-e/
一旦你打开页面,就滚动到提供的示例下面。例如,我选择了旧金山 Alamo Square 的照片作为提示:
图 15.17:旧金山 Alamo Square 的提示
然后我将“在晚上”修改为“在早晨”:
图 15.18:修改提示
DALL-E 然后生成了大量的 text2image
图像:
图 15.19:从文本提示生成图像
我们已经实现了 ViT、CLIP 和 DALL-E,三种视觉Transformers。在结束之前,让我们简要总结一下。
一个不断扩大的模型宇宙
新的Transformers模型,就像新的智能手机一样,几乎每周都会出现。其中一些模型既令人惊叹又对项目经理构成挑战:
- ERNIE 是一个持续的预训练框架,为语言理解提供了令人印象深刻的结果。
论文:arxiv.org/abs/1907.12412
挑战:Hugging Face 提供了一个模型。这是一个完整的模型吗?这是百度训练的超越人类基线的模型吗(2021 年 12 月):super.gluebenchmark.com/leaderboard
?我们是否可以访问到最好的模型还是只有一个玩具模型?对于这样小型模型运行 AutoML 的目的是什么?我们是否能在百度平台或类似平台上获得访问权限?这会花费多少? - SWITCH:一个经过稀疏建模优化的万亿参数模型。
论文:arxiv.org/abs/2101.03961
挑战:这篇论文很棒。模型在哪里?我们将永远能够访问到真正完全训练好的模型吗?会花费多少? - Megatron-Turing:一个拥有 5000 亿参数的Transformers模型。
博客:developer.nvidia.com/blog/using-deepspeed-and-megatron-to-train-megatron-turing-nlg-530b-the-worlds-largest-and-most-powerful-generative-language-model/
挑战:市场上最好的模型之一。我们是否可以通过 API 访问?它是否会是一个成熟的模型?会花费多少? - XLNET 像 BERT 一样进行了预训练,但作者认为它超过了 BERT 模型的性能。
论文:proceedings.neurips.cc/paper/2019/file/dc6a7e655d7e5840e66733e9ee67cc69-Paper.pdf
挑战:XLNET 是否真的超过了 Google BERT 的性能,Google 用于其活动的版本?我们是否可以访问到 Google BERT 或 XLNET 模型的最佳版本?
列表已经变得无穷无尽,而且还在增长!
测试它们仍然是一个超出前述问题的挑战。只有少数Transformers模型符合基础模型的条件。基础模型必须是:
- 完全训练,可执行一系列任务
- 能够执行其未经训练的任务,因为它已经达到了独特的 NLU 水平
- 足够大以保证相当准确的结果,比如 OpenAI GPT-3
许多网站提供的Transformers对于教育目的而言是有用的,但不能被视为足够训练和庞大以符合基准测试的。
最好的方法是尽可能地加深对Transformers模型的理解。在某个时刻,你会成为一名专家,通过大型技术创新的丛林将变得像选择智能手机一样容易!
摘要
新的Transformers模型不断出现在市场上。因此,通过阅读出版物和书籍,并测试一些系统,跟上前沿研究是一个好的实践。
这导致我们评估选择哪些Transformers模型以及如何实现它们。我们不能花几个月时间探索每个出现在市场上的模型。如果一个项目正在生产中,我们不能每个月都更换模型。工业 4.0 正在转向无缝的 API 生态系统。
学习所有模型是不可能的。然而,通过加深对Transformers模型的了解,可以快速理解一个新模型。
Transformers模型的基本结构保持不变。编码器和/或解码器堆栈的层保持相同。注意力头可以并行化以优化计算速度。
Reformer 模型应用LSH桶和分块。它还重新计算每个层的输入,而不是存储信息,从而优化了内存问题。然而,像 GPT-3 这样的十亿参数模型对于相同的示例产生可接受的结果。
DeBERTa 模型分解内容和位置,使训练过程更加灵活。结果令人印象深刻。然而,像 GPT-3 这样的十亿参数模型可以与 DeBERTa 的输出相媲美。
ViT、CLIP 和 DALL-E 带我们进入了迷人的任务无关的文本图像视觉Transformers模型的世界。结合语言和图像会产生新的、富有成效的信息。
问题仍然存在,即现成的人工智能和自动化系统将走多远。我们将尝试在下一章关于元人类崛起的章节中可视化基于Transformers的人工智能的未来。
问题
- Reformer Transformers模型不包含编码器。(True/False)
- Reformer Transformers模型不包含解码器。(True/False)
- 输入在 Reformer 模型中按层存储。(True/False)
- DeBERTa Transformers模型分解内容和位置。(True/False)
- 在选择项目使用的预训练Transformers模型之前,有必要测试数百个预训练的Transformers模型。(True/False)
- 最新的Transformers模型总是最好的。(True/False)
- 每个自然语言处理任务最好有一个Transformers模型,而不是一个多任务Transformers模型。(True/False)
- 一个Transformers模型总是需要进行微调。(True/False)
- OpenAI GPT-3 引擎可以在不进行微调的情况下执行广泛的自然语言处理任务。(True/False)
- 在本地服务器上实现 AI 算法总是更好的。(True/False)
参考文献
- Hugging Face Reformer:
huggingface.co/transformers/model_doc/reformer.html?highlight=reformer
- Hugging Face DeBERTa:
huggingface.co/transformers/model_doc/deberta.html
- Pengcheng He,Xiaodong Liu,Jianfeng Gao,Weizhu Chen,2020 年,Decoding-enhanced BERT with Disentangled Attention:
arxiv.org/abs/2006.03654
- Alexey Dosovitskiy, Lucas Beyer, Alexander Kolesnikov, Dirk Weissenborn, Xiaohua Zhai, Thomas Unterthiner, Mostafa Dehghani, Matthias Minderer, Georg Heigold, Sylvain Gelly, Jakob Uszkoreit, Neil Houlsby, 2020 年,一张图片等于 16x16 个单词: Transformers for Image Recognition at Scale:
arxiv.org/abs/2010.11929
- OpenAI:
openai.com/
- William Fedus, Barret Zoph, Noam Shazeer,2021 年,Switch Transformers: Scaling to Trillion Parameter Models with Simple and Efficient Sparsity:
arxiv.org/abs/2101.03961
- Alec Radford, Jong Wook Kim, Chris Hallacy, Aditya Ramesh, Gabriel Goh, Sandhini Agarwal, Girish Sastry, Amanda Askell, Pamela Mishkin, Jack Clark, Gretchen Krueger, Ilya Sutskever, 2021, Learning Transferable Visual Models From Natural Language Supervision:
arxiv.org/abs/2103.00020
- C7LIP:
github.com/openai/CLIP
- Aditya Ramesh, Mikhail Pavlov, Gabriel Goh, Scott Gray, Chelsea Voss, Alec Radford, Mark Chen, Ilya Sutskever, 2021, Zero-Shot Text-to-Image Generation:
arxiv.org/abs/2102.12092
- DALL-E:
openai.com/blog/dall-e/
加入我们书籍的 Discord 空间
加入书籍的 Discord 工作空间,与作者进行每月的问我任何事会话: