Hugging Face 的 Transformers 库快速入门(一)– pipelines 使用与模型

王 茂南 2022年12月13日07:08:26
评论
1 14063字阅读46分52秒
摘要本文是对 Hugging Face 的 Transformers 库的快速入门,包括如何快速使用该库来建立一个文本生成器,以及简单介绍「分词器」和「模型」。

简介

Transformers 是由 Hugging Face 开发的一个 NLP 包,支持加载目前绝大部分的预训练模型。随着 BERTGPT 等大规模语言模型的兴起,越来越多的公司和研究者采用 Transformers 库来构建 NLP 应用,因此熟悉 Transformers 库的使用方法很有必要(最近也是看了 Decision Transformer 的相关代码,使用了 Hugging Face 的相关内容,因此在这里系统的看一下)。

本文的主要是对下面参考链接一和链接二的内容进行了整理。会简单介绍 Transformers 的使用,和 Transformers 库中的两个重要组件:模型Models 类)和分词器Tokenizers 类)。

 

参考链接

 

开箱即用的 pipelines

Transformers 库最基础的对象就是 pipeline() 函数,它封装了预训练模型和对应的前处理和后处理环节。我们只需输入文本,就能得到预期的答案。目前常用的 pipelines 有:

  • feature-extraction (获得文本的向量化表示)
  • fill-mask (填充被遮盖的词、片段)
  • ner(命名实体识别)
  • question-answering (自动问答)
  • sentiment-analysis (情感分析)
  • summarization (自动摘要)
  • text-generation (文本生成)
  • translation (机器翻译)
  • zero-shot-classification (零训练样本分类)

 

Pipelines 的简单使用

下面看一个使用 pipeline() 函数来进行「文本生成」的例子。我们指定任务和使用的模型,来生成中文的古诗:

  1. from transformers import pipeline
  2. generator = pipeline("text-generation", model="uer/gpt2-chinese-poem")
  3. results = generator(
  4.     "[CLS] 万 叠 春 山 积 雨 晴 ,",
  5.     num_return_sequences=2,
  6.     max_length=50
  7. )
  8. print(results)

运行之后可以生成如下的内容:

  1. [
  2.     {'generated_text': '[CLS] 万 叠 春 山 积 雨 晴 , 烟 消 云 霁 列 峰 生 。 遥 知 草 木 焦 枯 处 , 大 野 流 泉 水 自 清 。 成 新 式 式 金 堤 , 圣 德 神 功 已 尽 跻 。 不'},
  3.     {'generated_text': '[CLS] 万 叠 春 山 积 雨 晴 , 晓 看 沧 海 暮 云 生 。 千 峰 列 翠 依 遥 立 , 双 涧 分 流 自 在 鸣 。 猿 鸟 不 惊 人 世 远 , 鱼 龙 常 共 太 平 平 。 谁'}
  4. ]

 

Pipelines 背后做了什么

pipeline() 函数实际上封装了许多操作,下面我们就来了解一下它们背后究竟做了啥。以情感分析 pipeline 为例,我们运行下面的代码:

  1. from transformers import pipeline
  2. classifier = pipeline("sentiment-analysis")
  3. result = classifier("I've been waiting for a HuggingFace course my whole life.")
  4. print(result)

就可以得到结果:

  1. [{'label': 'POSITIVE', 'score': 0.9598048329353333}]

实际上它的背后经过了三个步骤:

  1. 预处理 (preprocessing),将原始文本转换为模型可以接受的输入格式;
  2. 将处理好的输入送入模型;
  3. 对模型的输出进行后处理 (postprocessing),将其转换为人类方便阅读的格式。
Hugging Face 的 Transformers 库快速入门(一)– pipelines 使用与模型

 

使用分词器进行预处理

因为神经网络模型无法直接处理文本,因此首先需要通过预处理环节将文本转换为模型可以理解的数字。具体地,我们会使用每个模型对应的分词器 (tokenizer) 来进行:

  1. 将输入切分为词语、子词或者符号(例如标点符号),统称为 tokens
  2. 根据模型的词表将每个 tokens 映射到对应的 token 编号(就是一个数字)
  3. 根据模型的需要,添加一些额外的输入。

我们对输入文本的预处理需要与模型自身预训练时的操作完全一致,只有这样模型才可以正常地工作。注意,每个模型都有特定的预处理操作,如果对要使用的模型不熟悉,可以通过 Model Hub 查询。这里我们使用 AutoTokenizer 类和它的 from_pretrained() 函数,它可以自动根据模型 checkpoint 名称来获取对应的分词器。

情感分析 pipeline 的默认 checkpoint 是 distilbert-base-uncased-finetuned-sst-2-english,下面我们手工下载并调用其分词器:

  1. from transformers import AutoTokenizer
  2. checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
  3. tokenizer = AutoTokenizer.from_pretrained(checkpoint)
  4. raw_inputs = [
  5.     "I've been waiting for a HuggingFace course my whole life.",
  6.     "I hate this so much!",
  7. ]
  8. inputs = tokenizer(raw_inputs, padding=True, truncation=True, return_tensors="pt")
  9. print(inputs)

输入的结果如下所是,上面的 truncation 表示「截断操作」:

  1. {
  2.     'input_ids': tensor([
  3.         [  101,  1045,  1005,  2310,  2042,  3403,  2005,  1037, 17662, 12172, 2607,  2026,  2878,  2166,  1012,   102],
  4.         [  101,  1045,  5223,  2023,  2061,  2172,   999,   102,     0,     0,
  5.              0,     0,     0,     0,     0,     0]
  6.     ]),
  7.     'attention_mask': tensor([
  8.         [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
  9.         [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]
  10.     ])
  11. }

上面输出中包含两个键 input_ids 和 attention_mask,其中:

  • input_ids 对应分词之后的 tokens 映射到的数字编号列表;
  • attention_mask 则是用来标记哪些 tokens 是被填充的(这里“1”表示是原文,“0”表示是填充字符);

 

将预处理好的输入送入模型

预训练模型的下载方式和分词器 (tokenizer) 类似,Transformers 包提供了一个 AutoModel 类和对应的 from_pretrained() 函数。下面我们手工下载这个 distilbert-base 模型:

  1. from transformers import AutoModel
  2. checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
  3. model = AutoModel.from_pretrained(checkpoint)

预训练模型的本体只包含基础的 Transformer 模块,对于给定的输入,它会输出一些神经元的值,称为 hidden states 或者特征 (features)。对于 NLP 模型来说,可以理解为是文本的高维语义表示。这些 hidden states 通常会被输入到其他的模型部分(称为 head)(也就是上面的模型是没有 head 的),以完成特定的任务,例如送入到分类头中完成文本分类任务。

基本所有的模型都有类似的模型结构,只有模型的最后一个部分会使用不同的 head 来完成相应的任务。下图是一个简单的例子:

Hugging Face 的 Transformers 库快速入门(一)– pipelines 使用与模型

Transformer 模块的输出是一个维度为 (Batch size, Sequence length, Hidden size) 的三维张量,其中

  • Batch size 表示每次输入的样本(文本序列)数量,即每次输入多少个句子,上例中为 2;
  • Sequence length 表示文本序列的长度,即每个句子被分为多少个 token,上例中为 16;
  • Hidden size 表示每一个 token 经过模型编码后的输出向量(语义表示)的维度(预训练模型编码后的输出向量的维度通常都很大,例如 Bert 模型 base 版本的输出为 768 维,一些大模型的输出维度为 3072 甚至更高)。

这里我们打印出 distilbert-base 模型的输出维度,将 input 输入模型:

  1. from transformers import AutoTokenizer
  2. from transformers import AutoModel
  3. # 对 input 进行预处理
  4. checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
  5. tokenizer = AutoTokenizer.from_pretrained(checkpoint)
  6. raw_inputs = [
  7.     "I've been waiting for a HuggingFace course my whole life.",
  8.     "I hate this so much!",
  9. ]
  10. inputs = tokenizer(raw_inputs, padding=True, truncation=True, return_tensors="pt")
  11. print(inputs)
  12. # 加载模型并输出
  13. checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
  14. model = AutoModel.from_pretrained(checkpoint)
  15. output = model(**inputs) # 将 input 传入 model
  16. print(output.last_hidden_state.shape)

Transformers 模型的输出格式类似 namedtuple 或字典,可以像上面那样通过属性访问,也可以通过键(outputs["last_hidden_state"]),甚至索引访问(outputs[0])。上面模型输出的大小如下所是:

  1. torch.Size([2, 16, 768])

对于情感分析任务,很明显我们最后需要使用的是一个「二分类 head」。因此,实际上我们不会使用 AutoModel 类,而是使用 AutoModelForSequenceClassification

  1. from transformers import AutoTokenizer
  2. from transformers import AutoModelForSequenceClassification
  3. checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
  4. tokenizer = AutoTokenizer.from_pretrained(checkpoint)
  5. model = AutoModelForSequenceClassification.from_pretrained(checkpoint)
  6. raw_inputs = [
  7.     "I've been waiting for a HuggingFace course my whole life.",
  8.     "I hate this so much!",
  9. ]
  10. inputs = tokenizer(raw_inputs, padding=True, truncation=True, return_tensors="pt")
  11. outputs = model(**inputs)
  12. print(outputs.logits.shape)

最后输出的结果如下。可以看到,对于 batch 中的每一个样本,模型都会输出一个两维的向量(每一维对应一个标签,positive 或 negative)。

  1. torch.Size([2, 2])

 

对模型输出进行后处理

由于模型的输出只是一些数值,因此并不适合人类阅读。例如我们打印出上面例子的输出:

  1. tensor([[-1.5607,  1.6123],
  2.         [ 4.1692, -3.3464]], grad_fn=<AddmmBackward0>)

模型对第一个句子输出 [-1.57, 1.61],对第二个句子输出 [4.16, -3.34],它们并不是概率值,而是模型最后一层输出的 logits 值(所有 Transformers 模型都会输出 logits 值,因为训练时的损失函数通常会自动结合激活函数,例如 SoftMax,与实际的损失函数,例如交叉熵 cross entropy)。要将他们转换为概率值,还需要让它们经过一个 SoftMax 层,例如:

  1. import torch
  2. predictions = torch.nn.functional.softmax(outputs.logits, dim=-1)
  3. print(predictions)

经过上面的输出之后,模型就可以输出易于理解的概率值了。

  1. tensor([[4.0195e-02, 9.5980e-01],
  2.         [9.9946e-01, 5.4418e-04]], grad_fn=<SoftmaxBackward0>)
  3. {0: 'NEGATIVE', 1: 'POSITIVE'}

于是我们可以得到最终的预测结果如下:

  • 第一个句子: NEGATIVE: 0.0402, POSITIVE: 0.9598
  • 第二个句子: NEGATIVE: 0.9995, POSITIVE: 0.0005

 

模型

在之前介绍 pipeline 模型时,我们使用 AutoModel 类根据 checkpoint 名称自动加载模型。当然,我们也可以直接使用对应的 Model 类。例如加载 BERT 模型(包括采用 BERT 结构的其他模型):

  1. from transformers import BertModel
  2. model = BertModel.from_pretrained("bert-base-cased")

 

加载模型

通过调用 Model.from_pretrained() 函数可以自动加载 checkpoint 对应的模型权重 (weights)。然后,我们可以直接使用模型完成它的预训练任务,或者在新的任务上对模型权重进行微调。

Model.from_pretrained() 会自动缓存下载的模型权重,默认保存到 ~/.cache/huggingface/hub,我们也可以通过 HF_HOME 环境变量自定义缓存目录。

所有存储在 Model Hub 上的模型都能够通过 Model.from_pretrained() 加载,只需要传递对应 checkpoint 的名称。当然了,我们也可以先将模型下载下来,然后将本地路径传给 Model.from_pretrained(),比如加载下载好的 Bert-base 模型

  1. from transformers import BertModel
  2. model = BertModel.from_pretrained("./models/bert/")

部分模型的 Hub 页面中会包含很多文件,我们通常只需要下载:

  • 模型对应的 config.json 和 pytorch_model.bin
  • 分词器对应的 tokenizer.jsontokenizer_config.json 和 vocab.txt

 

保存模型

保存模型与加载模型类似,只需要调用 Model.save_pretrained() 函数。例如保存加载的 BERT 模型:

  1. from transformers import AutoModel
  2. model = AutoModel.from_pretrained("bert-base-cased")
  3. model.save_pretrained("./models/bert-base-cased/")

这会在保存路径下创建两个文件:

  • config.json:模型配置文件,里面包含构建模型结构的必要参数;
  • pytorch_model.bin:又称为 state dictionary,包含模型的所有权重。

这两个文件缺一不可,配置文件负责记录模型的结构,模型权重记录模型的参数。我们自己保存的模型同样可以通过 Model.from_pretrained() 加载,只需要传递保存目录的路径。下面是 config.json 文件的大致内容:

Hugging Face 的 Transformers 库快速入门(一)– pipelines 使用与模型

 

分词器

因为神经网络模型不能直接处理文本,我们需要先将文本转换为模型能够处理的数字,这个过程被称为编码 (Encoding):先使用分词器 (Tokenizers) 将文本按词、子词、符号切分为 tokens;然后将 tokens 映射到对应的 token 编号(token IDs)。

 

分词策略

根据切分粒度的不同,分词策略大概可以分为以下几种,关于这部分详细内容可以查看链接 分词策略

  • 按词切分(Word-based)
  • 按字符切分(Character-based)
  • 按子词切分(Subword-based)

目前按子词切分 (Subword tokenization) 是一种被广泛采用的方式。按子词 (Subword) 切分 高频词直接保留,低频词被切分为更有意义的子词。

例如 “annoyingly” 就是一个低频词,可以切分为 “annoying” 和 “ly”,这两个子词不仅出现频率更高,而且词义也得以保留。下图就是对文本 “Let’s do tokenization!“ 按子词切分的例子:

Hugging Face 的 Transformers 库快速入门(一)– pipelines 使用与模型

可以看到,“tokenization” 被切分为了 “token” 和 “ization”,不仅保留了语义,而且只用两个 token 就表示了一个长词。这中策略只用一个较小的词表就可以覆盖绝大部分的文本,基本不会产生 unknown tokens。尤其对于土耳其语等黏着语言,可以通过串联多个子词构成几乎任意长度的复杂长词。

 

加载和保存分词器

分词器的加载与保存与模型非常相似,也是使用 from_pretrained() 和 save_pretrained() 函数。例如,使用 BertTokenizer 类加载并保存 BERT 模型的分词器:

  1. from transformers import BertTokenizer
  2. tokenizer = BertTokenizer.from_pretrained("bert-base-cased")
  3. tokenizer.save_pretrained("./models/bert-base-cased/")

与 AutoModel 类似,在大部分情况下,我们都应该使用 AutoTokenizer 类来加载分词器,它会根据 checkpoint 来自动选择对应的分词器(使用的接口是与上面一致的):

  1. from transformers import AutoTokenizer
  2. tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
  3. tokenizer.save_pretrained("./models/bert-base-cased/")

调用 Tokenizer.save_pretrained() 函数会在保存路径下创建三个文件:

  • special_tokens_map.json:配置文件,里面包含 unknown tokens 等特殊字符的映射关系;
  • tokenizer_config.json:配置文件,里面包含构建分词器需要的参数;
  • vocab.txt:词表,每一个 token 占一行,行号就是对应的 token ID(从 0 开始)。

下面是 special_tokens_map.json 文件对应的内容:

  1. {
  2.     "unk_token": "[UNK]",
  3.     "sep_token": "[SEP]",
  4.     "pad_token": "[PAD]",
  5.     "cls_token": "[CLS]",
  6.     "mask_token": "[MASK]"
  7. }

 

编码和解码文本

完整的文本编码 (Encoding) 过程实际上包含两个步骤:

  1. 分词:使用分词器按某种策略将文本切分为 tokens(也就是将);
  2. 映射:将 tokens 转化为对应的 token IDs。

因为不同预训练模型采用的分词策略并不相同,因此我们需要通过向 Tokenizer.from_pretrained() 函数传递模型 checkpoint 的名称来加载对应的分词器和词表。

 

分词与映射分别操作

下面,我们尝试使用 BERT 分词器来对文本进行分词:

  1. from transformers import AutoTokenizer
  2. tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
  3. sequence = "Using a Transformer network is simple"
  4. tokens = tokenizer.tokenize(sequence)
  5. print(tokens)

输出的结果如下所是。可以看到,BERT 分词器采用的是子词 (subword) 切分策略,它会不断切分词语直到获得词表中的 token,例如 “transformer” 会被切分为 “trans” 和 “##former”。

  1. ['Using', 'a', 'Trans', '##former', 'network', 'is', 'simple']

然后,我们通过 convert_tokens_to_ids() 将切分出的 tokens 转换为对应的 token IDs:

  1. ids = tokenizer.convert_tokens_to_ids(tokens)
  2. print(ids)

输出的结果如下所是,也就是将上面的字符转换为了 id:

  1. [7993, 170, 13809, 23763, 2443, 1110, 3014]

 

使用 encode 完成编码

我们也可以通过 encode() 函数将这两个步骤合并,并且 encode() 会自动添加模型需要的特殊字符。例如对于 BERT 会自动在 token 序列的首尾分别添加 [CLS] 和 [SEP] token:

  1. from transformers import AutoTokenizer
  2. tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
  3. sequence = "Using a Transformer network is simple"
  4. sequence_ids = tokenizer.encode(sequence)
  5. print(sequence_ids)

输出的结果如下所是,其中 101 和 102 分别是 [CLS] 和 [SEP] 对应的 token IDs:

  1. [101, 7993, 170, 13809, 23763, 2443, 1110, 3014, 102]

 

使用 decode 完成解码

文本解码 (Decoding) 与编码相反,负责将 token IDs 转化为原来的字符串。注意,解码过程不是简单地将 token IDs 映射回 tokens,还需要合并那些被分词器分为多个 token 的单词。下面我们尝试通过 decode() 函数解码前面生成的 token IDs:

  1. from transformers import AutoTokenizer
  2. tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
  3. decoded_string = tokenizer.decode([101, 7993, 170, 13809, 23763, 2443, 1110, 3014, 102])
  4. print(decoded_string)

最终的结果如下所是,可以看到成功将 ID 还原为 tokens

  1. [CLS] Using a Transformer network is simple [SEP]

 

直接使用分词器处理

实际编码文本时,更为常见的是直接使用分词器进行处理。这样返回的结果中不仅包含处理后的 token IDs,还包含模型需要的其他辅助输入。例如对于 BERT 模型还会自动在输入中添加 token_type_ids 和 attention_mask

  1. from transformers import AutoTokenizer
  2. tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")
  3. tokenized_text = tokenizer("Using a Transformer network is simple")
  4. print(tokenized_text)

最终的结果如下所是:

  1. {
  2.     'input_ids': [101, 7993, 170, 13809, 23763, 2443, 1110, 3014, 102],
  3.     'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0],
  4.     'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1]
  5. }

 

处理多段文本

在实际应用中,我们往往需要同时处理大量长度各异的文本。而且所有的神经网络模型都只接受批 (batch) 数据作为输入,即使只输入一段文本,也需要先将它组成只包含一个样本的 batch,然后才能送入模型。

使用分词器处理多个句子

同样的,我们可以直接使用「分词器」对文本进行处理。下面看一个例子,共有两句话:

  1. from transformers import AutoTokenizer
  2. # 加载分词器
  3. checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
  4. tokenizer = AutoTokenizer.from_pretrained(checkpoint)
  5. # 句子
  6. sequence = [
  7.     "I've been waiting for a HuggingFace course my whole life.",
  8.     "Hello, World."
  9. ]
  10. # 分词
  11. tokenized_inputs = tokenizer(sequence, padding=True, return_tensors="pt")
  12. print("Input IDs:\n", tokenized_inputs)

输出的结果为,可以看到通过 padding 使得输出长度是一样的。

  1. {
  2.     'input_ids': tensor([
  3.         [
  4.           101,  1045,  1005,  2310,  2042,  3403,  2005,  1037, 17662, 12172,
  5.           2607,  2026,  2878,  2166,  1012,   102],
  6.         [
  7.             101,  7592,  1010,  2088,  1012,   102,     0,     0,     0,     0,
  8.             0,     0,     0,     0,     0,     0
  9.         ]
  10.     ]),
  11.     'attention_mask': tensor([
  12.         [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
  13.         [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  14.     ])
  15. }

这里通过 return_tensors 参数指定返回的张量格式:设为 pt 则返回 PyTorch 张量;tf 则返回 TensorFlow 张量,np 则返回 NumPy 数组。

通过 Padding 操作,在短序列的最后填充特殊的 padding token,使得 batch 中所有的序列都具有相同的长度。padding 有以下的参数来控制:

  • padding="longest": 将 batch 内的序列填充到当前 batch 中最长序列的长度;
  • padding="max_length":将所有序列填充到模型能够接受的最大长度,例如 BERT 模型就是 512。

截断操作通过 truncation 参数来控制,如果 truncation=True,那么大于模型最大接受长度的序列都会被截断,例如对于 BERT 模型就会截断长度超过 512 的序列。此外,也可以通过 max_length 参数来控制截断长度:

  1. model_inputs = tokenizer(sequences, max_length=8, truncation=True)

 

Attention Masks

使用 padding 会存在一个问题,Transformer 模型会编码输入序列中的每一个 token 以建模完整的上下文。因此会将填充的 padding token 也当成是普通 token 一起编码,从而生成了不同的上下文语义表示。也就是导致加入 padding 之后的结果会和加入前是不一样的。

因此,在进行 Padding 操作的同时,我们必须明确地告诉模型哪些 token 是我们填充的,它们不应该参与编码,这就需要使用到 attention mask

Attention masks 是一个与 input IDs 尺寸完全相同的仅由 0 和 1 组成的张量,其中 0 表示对应位置的 token 是填充符,不应该参与 attention 层的计算,而应该只基于 1 对应位置的 token 来建模上下文。

 

编码句子对

在上面的例子中,我们都是对单个序列进行编码(即使通过 batch 处理多段文本,也是并行地编码单个序列),而实际上对于 BERT 等包含「句子对」分类预训练任务的模型来说,都支持对「句子对」进行编码,例如:

  1. from transformers import AutoTokenizer
  2. checkpoint = "bert-base-uncased"
  3. tokenizer = AutoTokenizer.from_pretrained(checkpoint)
  4. inputs = tokenizer("This is the first sentence.", "This is the second one.")
  5. print(inputs)
  6. tokens = tokenizer.convert_ids_to_tokens(inputs["input_ids"])
  7. print(tokens)

输出的结果是:

  1. {
  2.     'input_ids': [101, 2023, 2003, 1996, 2034, 6251, 1012, 102, 2023, 2003, 1996, 2117, 2028, 1012, 102],
  3.     'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1],
  4.     'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
  5. }
  6. ['[CLS]', 'this', 'is', 'the', 'first', 'sentence', '.', '[SEP]', 'this', 'is', 'the', 'second', 'one', '.', '[SEP]']

可以看到分词器自动使用 [SEP] token 拼接了两个句子,输出形式为「[CLS] sentence1 [SEP] sentence2 [SEP]」的 token 序列,这也是 BERT 模型预期的输入格式。

返回结果中除了前面我们介绍过的 input_ids 和 attention_mask 之外,还包含了一个 token_type_ids 项,用于标记输入序列中哪些 token 属于第一个句子,哪些属于第二个句子。也就是第一个句子「[CLS] sentence1 [SEP]」的 token_type_ids 都是 0,而第二个句子 「sentence2 [SEP]」对应的 token_type_ids 都是 0

下面是一个包含句子对和多个句子的分词器使用的例子:

  1. from transformers import AutoTokenizer
  2. checkpoint = "bert-base-uncased"
  3. tokenizer = AutoTokenizer.from_pretrained(checkpoint)
  4. sentences_list = [
  5.     ["This is the first sentence 1.", "second sentence 1."],
  6.     ["This is the first sentence 2.", "second sentence 2."]
  7.     ]
  8. tokens = tokenizer(
  9.     sentences_list,
  10.     padding=True,
  11.     truncation=True,
  12.     return_tensors="pt"
  13. )
  14. print(tokens)

  • 微信公众号
  • 关注微信公众号
  • weinxin
  • QQ群
  • 我们的QQ群号
  • weinxin
王 茂南
  • 本文由 发表于 2022年12月13日07:08:26
  • 转载请务必保留本文链接:https://mathpretty.com/15636.html
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: