当前位置: 首页 > news >正文

HuggingFace课程-2. 使用 Transformers 处理多个序列

处理多个序列

Ask a QuestionOpen In ColabOpen In Studio Lab

在上一节中,我们探讨了最简单的案例:对一个较短的句子进行推理。然而,一些问题已经出现:

  • 我们如何处理多个句子?

  • 我们如何处理不同长度的多个句子?

  • 词汇索引是唯一可以让模型运行的输入吗?

  • 是否存在句子太长的问题?

让我们看看这些问题会带来什么样的问题,以及如何使用🤗 Transformers API 解决它们

模型需要一批输入

在上一个练习中,你看到了句子如何转换为数字列表。让我们将此数字列表转换为张量,并将其发送到模型:

import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassificationcheckpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)sequence = "I've been waiting for a HuggingFace course my whole life."tokens = tokenizer.tokenize(sequence)
ids = tokenizer.convert_tokens_to_ids(tokens)
input_ids = torch.tensor(ids)
# 这一行会运行失败
model(input_ids)
IndexError: Dimension out of range (expected to be in range of [-1, 0], but got 1)

哦,不!为什么失败了?“我们的确是按照第 2 节中管道的步骤一步步来做的。

问题是我们向模型发送了一个单独的句子,而🤗 Transformers 模型默认情况下需要一个句子列表。在这里,当我们试图重现 tokenizer 在输入 sequence 后在其内部进行的所有操作。但如果你仔细观察,你会发现 tokenizer 不仅仅是将 inputs ID 的列表转换为张量,它还在其上添加了一个维度:

tokenized_inputs = tokenizer(sequence, return_tensors="pt")
print(tokenized_inputs["input_ids"])
tensor([[  101,  1045,  1005,  2310,  2042,  3403,  2005,  1037, 17662, 12172,2607,  2026,  2878,  2166,  1012,   102]])

让我们再试一次并添加一个新的维度:

import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassificationcheckpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)sequence = "I've been waiting for a HuggingFace course my whole life."tokens = tokenizer.tokenize(sequence)
ids = tokenizer.convert_tokens_to_ids(tokens)input_ids = torch.tensor([ids])
print("Input IDs:", input_ids)output = model(input_ids)
print("Logits:", output.logits)

让我们打印 inputs ID 以及生成的 logits 值,以下是输出:

Input IDs: [[ 1045,  1005,  2310,  2042,  3403,  2005,  1037, 17662, 12172,  2607, 2026,  2878,  2166,  1012]]
Logits: [[-2.7276,  2.8789]]

批处理(Batching)是一次性通过模型发送多个句子的行为。如果你只有一句话,你可以构建一个只有一个句子的 batch:

batched_ids = [ids, ids]

这就是一个包含两个相同句子的 batch

✏️ 试试看! 将这个 batched_ids 列表转换为张量,并通过你的模型进行处理。检查你是否得到了与之前相同的 logits 值(但是重复了两次)!

批处理支持模型在输入多个句子时工作。使用多个句子就像使用单个句子构建批一样简单。不过,还有第二个问题。当你试图将两个(或更多)句子组合在一起时,它们的长度可能不同。如果你以前使用过张量,那么你知道它们必须是矩形,因此无法将 inputs ID 列表直接转换为张量。为了解决这个问题,我们通常填充输入(Padding)。

填充输入(Padding)

以下列表不能转换为张量:

batched_ids = [[200, 200, 200],[200, 200]
]

为了解决这个问题,我们将使用填充使张量成为标准的矩形。Padding 通过在值较少的句子中添加一个名为 padding_id 的特殊单词来确保我们所有的句子长度相同。例如,如果你有 10 个包含 10 个单词的句子和 1 个包含 20 个单词的句子,填充能确保所有句子都包含 20 个单词。在我们的示例中,填充后的张量如下所示:

padding_id = 100batched_ids = [[200, 200, 200],[200, 200, padding_id],
]

我们可以在 tokenizer.pad_token_id 中找到填充 token 的 ID。让我们使用它,分别用模型处理这两个句子,然后再尝试将这两个句子放在一起用模型批处理:

model = AutoModelForSequenceClassification.from_pretrained(checkpoint)sequence1_ids = [[200, 200, 200]]
sequence2_ids = [[200, 200]]
batched_ids = [[200, 200, 200],[200, 200, tokenizer.pad_token_id],
]print(model(torch.tensor(sequence1_ids)).logits)
print(model(torch.tensor(sequence2_ids)).logits)
print(model(torch.tensor(batched_ids)).logits)
tensor([[ 1.5694, -1.3895]], grad_fn=<AddmmBackward>)
tensor([[ 0.5803, -0.4125]], grad_fn=<AddmmBackward>)
tensor([[ 1.5694, -1.3895],[ 1.3373, -1.2163]], grad_fn=<AddmmBackward>)

咦,我们批处理预测中的 logits 值有点问题:第二行应该与第二句的 logits 相同,但我们得到了完全不同的值!

这是因为 Transformer 模型的关键特性:注意力层,它考虑了每个 token 的上下文信息。这具体来说,每个 token 的含义并非单独存在的,它的含义还取决于它在句子中的位置以及周围的其他 tokens。当我们使用填充(padding)来处理长度不同的句子时,我们会添加特殊的“填充 token”来使所有句子达到相同的长度。但是,注意力层会将这些填充 token 也纳入考虑,因为它们会关注序列中的所有 tokens。这就导致了一个问题:尽管填充 token 本身并没有实际的含义,但它们的存在会影响模型对句子的理解。我们需要告诉这些注意层忽略填充 token。这是通过使用注意力掩码(attention mask)层来实现的。

注意力掩码(attention mask)层

注意力掩码(attention mask)是与 inputs ID 张量形状完全相同的张量,用 0 和 1 填充:1 表示应关注相应的 tokens,0 表示应忽略相应的 tokens(即,它们应被模型的注意力层忽视)。

让我们用 attention mask 修改上一个示例:

batched_ids = [[200, 200, 200],[200, 200, tokenizer.pad_token_id],
]attention_mask = [[1, 1, 1],[1, 1, 0],
]outputs = model(torch.tensor(batched_ids), attention_mask=torch.tensor(attention_mask))
print(outputs.logits)
tensor([[ 1.5694, -1.3895],[ 0.5803, -0.4125]], grad_fn=<AddmmBackward>)

现在我们得到了批处理中第二句话相同的 logits 值。

注意第二序列的最后一个值是填充 ID,其在注意力掩码中的值为 0。

✏️ 试试看!在第二节使用的两个句子(“I’ve been waiting for a HuggingFace course my whole life.” 和 “I hate this so much!”)上手动进行 tokenize。将它们输入模型并检查你是否得到了与第二节相同的 logits 值。然后使用填充 token 将它们一起进行批处理,然后创建合适的注意力掩码。检查模型计算后是否得到了相同的结果!

更长的句子

对于 Transformers 模型,我们可以通过模型的序列长度是有限的。大多数模型处理多达 512 或 1024 个 的 tokens 序列,当使用模型处理更长的序列时,会崩溃。此问题有两种解决方案:

  • 使用支持更长序列长度的模型。
  • 截断你的序列。

不同的模型支持的序列长度各不相同,有些模型专门用于处理非常长的序列。例如 Longformer 和 LED 。如果你正在处理需要非常长序列的任务,我们建议你考虑使用这些模型。

另外,我们建议你通过设定 max_sequence_length 参数来截断序列:

sequence = sequence[:max_sequence_length]
http://www.sczhlp.com/news/40131/

相关文章:

  • Java测试类、工具类与JavaBean对比解析
  • FLEXnet 软件许可管理系统详解
  • 做网站播放未上映的电影营销100个引流方案
  • 自助建站凡科网建站seo推广
  • wordpress标签链接优化北京推广优化公司
  • 支付网站建设费账务处理百度seo白皮书
  • 做网站语言知乎推广软件是什么工作
  • 在企业网站建设的解决方案中宁波seo怎么做引流推广
  • 如何选择大连网站建设搜索引擎优化的内容
  • HuggingFace课程-2. 使用 Transformers 标记器(Tokenizer)
  • git 查询某段代码的修改历史
  • #边分治,虚树,欧拉序,LCA#洛谷 4220 [WC2018] 通道
  • 有个网站301什么教育培训班
  • html设计主题网站代码优化是什么梗
  • 怎么做一个自己的小程序网络优化这个行业怎么样
  • 网站开发补充合同新手怎么做网络推广
  • 美食网站黑米如何做百度开发者平台
  • 电子商务网站建设需求表网络销售是什么工作内容
  • 惠州网站建设是什么意思肇庆seo排名外包
  • 做网站用什么格式的图片深圳专业seo外包
  • 网站信息登记表四川刚刚发布的最新新闻
  • 电子商务 独立网站巨量引擎app
  • 做网站的怎么找客户友情链接检测结果
  • 网站建设需要哪些成本网址域名注册
  • 简述网站制作的流程qq群引流推广平台免费
  • 网站建设宣传文案锦州网站seo
  • linux系统打开wordpress桔子seo网
  • 网站开发的硬件设备华为云速建站
  • 用dede做的网站结构优化是什么意思
  • Vue 词云图 echart-wordCloud