文章目录
- 前言
- Using Transformers
- 使用tokenizer预处理
- Tokenizer详解
- Loading and saving
- 加载
- 保存
- Encoding
- Decoding
- Model
- 创建一个Transformer
- 不同的加载方法
- 模型保存
- 使用模型进行推理
前言
- 因实验中遇到很多
huggingface-transformers
模型和操作,因此打算随着 course 从头理一下 - 这个系列将会持续更新
- 后续应该也会学习一下
fairseq
框架
Using Transformers
我们以一个完整的样例开始,看看在处理的过程中到底发生了什么
from transformers import pipeline
classifier = pipeline("sentiment-analysis")
classifier(
[
"I've been waiting for a HuggingFace course my whole life.",
"I hate this so much!",
]
)
[{‘label’: ‘POSITIVE’, ‘score’: 0.9598047137260437},
{‘label’: ‘NEGATIVE’, ‘score’: 0.9994558095932007}]
这个pipeline包括三个部分:预处理,将输入输入模型中,后处理
使用tokenizer预处理
和其他模型一样,transformer
不能直接处理原始文本,我们首先用tokenizer
将文本转换成模型可以理解的 numbers。Tokenizer
有以下几个任务
- 将输入分成words, subwords 或者 symbols 等 token
- 将每个 token 映射成一个数字
- 添加额外的可能对模型有用的输入
我们使用预训练的Tokenizer
,通过 AutoTokenizer class
和其 from_pretrained()
方法来加载
from transformers import AutoTokenizer
checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
现在,我们可以向Tokenizer
中输入文本
raw_inputs = [
"I've been waiting for a HuggingFace course my whole life.",
"I hate this so much!",
]
inputs = tokenizer(raw_inputs, padding=True, truncation=True, return_tensors="pt")
print(inputs)
>>{
'input_ids': tensor([
[ 101, 1045, 1005, 2310, 2042, 3403, 2005, 1037, 17662, 12172, 2607, 2026, 2878, 2166, 1012, 102],
[ 101, 1045, 5223, 2023, 2061, 2172, 999, 102, 0, 0, 0, 0, 0, 0, 0, 0]
]),
'attention_mask': tensor([
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0]
])
}
我们可以输入一个句子或者一个句子列表,同时指定想要得到的 tensor
的类型
Transformers model 只接受 tensor 作为输入
输出的结果是包含两个 key
的字典:
input_ids
:attention_mask
Tokenizer详解
上面说过,Tokenizer
的功能就是将原始文本转换成模型可以理解的形式(numbers)。
分离文本的方式有很多,比如python
中的 .split()
函数,按照空格来将文本分离成 words。我们还可以用标点符号来分隔,使用这种tokenizer,最后会得到一个很大的“词典”,a vocabulary is defined by the total number of independent tokens that we have in our corpus。每个词都会被分配一个 id(从0开始),模型利用 id 来区分词。
不同分词方式详见:Tokenizers - Hugging Face Course
Loading and saving
基于两个方法: from_oretrained()
和 save_pretrained()
。这些方法会保存 tokenizer 使用的算法(类似模型结构)和使用的词典(类似模型权重)
加载
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-cased") # 根据checkpoint名字自动找到对应的class
#还可以直接加载特定的 tokennizer
tokenizer = BertTokenizer.from_pretrained("bert-base-cased")
保存
tokenizer.save_pretrained("directory_on_my_computer")
Encoding
我们来看看 input_ids
是如何生成的(encode),encode分成两步:
-
tokenization(split text into tokens)
tokenizer = AutoTokenizer.from_pretrained("bert-base-cased") sequence = "Using a Transformer network is simple" tokens = tokenizer.tokenize(sequence)
-
转换到 input IDs:当我们用
.from_pretrained()
实例化一个 tokenizer 时,会下载一个词典。我们通过词典来完成映射ids = tokenizer.convert_tokens_to_ids(tokens)
Decoding
Decoding做的是,当我们提供 ids 时(其实就是词汇表中token的索引),能得到ids对应的token。这时我们可以使用
decoded_string = tokenizer.decode([7993, 170, 11303, 1200, 2443, 1110, 3014])
print(decoded_string)
- decode()函数不仅将索引恢复成token,还能将属于同一个单词的 token 组合在一起,生成一个可读的句子
Model
创建一个Transformer
我们以BERT为例,实例化BERT的第一件事就是加载一个 configuration 对象
from transformers import BertConfig, BertModel
# Building the config
config = BertConfig()
# Building the model from the config
model = BertModel(config)
不同的加载方法
上面展示的是模型随机初始化的加载方式,同样,我们可以加载预训练模型
from transformers import BertModel
model = BertModel.from_pretrained("bert-base-cased")
权重会被下载并保存到cache(默认路径是*~/.cache/huggingface/transformers*
),通过设定HF_HOME
环境变量可以定制cache folder
模型保存
model.save_pretrained("directory_on_my_computer")
这会保存两个文件:
-
config.json
:包括构建模型结构必要的属性,还包括一些 metadata(上次保存使用的transformer版本等) -
pytorch_model.bin
:包括所有的模型权重 -
这两个文件是相辅相成的,一个可以知道模型架构,一个可以提供模型参数
使用模型进行推理
import torch
sequences = ["Hello!", "Cool.", "Nice!"]
encoded_sequences = [
[101, 7592, 999, 102],
[101, 4658, 1012, 102],
[101, 3835, 999, 102],
]
model_inputs = torch.tensor(encoded_sequences)
output = model(model_inputs)
- model可以接受很多不同的参数,但是只有 input_ids 是必须的
Tensors只接受矩形的数据,如果每一条数据的长度不同,转换成tensor会报错