0 评论

0 收藏

分享

【NLP-04】tranformers库保姆级使用教程---以BERT模型为例

安装

要安装一个非常轻量级的Transformers库,您可以执行以下步骤:

  • 1、打开终端或命令提示符。
  • 2、运行以下命令来安装Transformers库:
pip install transformers

这将使用pip工具从Python Package Index(PyPI)下载并安装Transformers库。请确保您的计算机上已经安装了pip。

然后,您可以在Python代码中导入Transformers库:

import transformers

这样就可以使用Transformers库中提供的功能了。

如果您想安装包含几乎所有用例所需依赖项的开发版本,可以执行以下步骤:

  • 1、打开终端或命令提示符。
  • 2、运行以下命令来安装Transformers库及其相关依赖项:
pip install transformers[sentencepiece]

这将安装Transformers库的开发版本,并包括用于处理句子拆分的SentencePiece依赖项。注意,这个版本可能比轻量级版本更大,因为它包含了更多的依赖项。

一、模型简介 Transformer models

Transformers库中的pipeline函数是一个非常方便的工具,可以直接使用预训练模型进行文本处理。下面是一些pipeline的简单示例:

image.png

1、情感分析(Sentiment Analysis):
from transformers import pipeline

classifier = pipeline("sentiment-analysis")
result = classifier("I've been waiting for a HuggingFace course my whole life.")

print(result)

输出:

[{'label': 'POSITIVE', 'score': 0.9598047137260437}]

您还可以传递多个句子进行情感分析:

results = classifier([
    "I've been waiting for a HuggingFace course my whole life.",
    "I hate this so much!"
])

print(results)

输出:

[{'label': 'POSITIVE', 'score': 0.9598047137260437},
 {'label': 'NEGATIVE', 'score': 0.9994558095932007}]
2、其他可用的pipeline:

除了情感分析,Transformers库还提供了其他一些可用的pipeline,如特征提取(feature-extraction)、命名实体识别(ner)、问答(question-answering)、摘要(summarization)、文本生成(text-generation)、翻译(translation)等。您可以根据需要选择适合您任务的pipeline。

例如,使用zero-shot-classification进行分类:

classifier = pipeline("zero-shot-classification")
result = classifier(
    "I've been waiting for a HuggingFace course my whole life.",
    candidate_labels=["positive", "negative"]
)

print(result)

输出:

{'sequence': "I've been waiting for a HuggingFace course my whole life.",
 'labels': ['positive', 'negative'],
 'scores': [0.9943647985458374, 0.00563523546639061]}

这些pipeline的具体例子可见:Transformer models - Hugging Face Course

3、各种任务的代表模型
Model Examples Tasks
Encoder 编码器模型 ALBERT, BERT, DistilBERT, ELECTRA, RoBERTa Sentence classification, named entity recognition, extractive question answering 适合需要理解完整句子的任务,例如句子分类、命名实体识别(以及更一般的单词分类)和提取式问答
Decoder 解码器模型 CTRL, GPT, GPT-2, Transformer XL Text generation 解码器模型的预训练通常围绕预测句子中的下一个单词。这些模型最适合涉及文本生成的任务
Encoder-decoder 序列到序列模型 BART, T5, Marian, mBART Summarization, translation, generative question answering 序列到序列模型最适合围绕根据给定输入生成新句子的任务,例如摘要、翻译或生成式问答。

本节测试:Transformer models - Hugging Face Course

二、 使用 Using Transformers

1、Pipeline 背后的流程

在使用Pipeline时,背后的流程包括三个主要步骤:分词器(Tokenizer)、模型(Model)和后处理(Post-Processing)。通过这三个步骤的组合,Pipeline能够接收原始文本作为输入,并使用预训练模型进行处理,最终生成相应的输出。这种流程的设计使得使用Transformers库进行文本处理变得简单且高效。

1)分词器(Tokenizer)
分词器用于将输入的原始文本分割成单词或子词的序列,以便模型能够理解和处理。它将文本转换为模型可以接受的输入格式。在Transformers库中,可以使用AutoTokenizer类及其from_pretrained()方法来实例化一个适用于特定预训练模型的分词器。
与其他神经网络一样,Transformer 模型不能直接处理原始文本,故使用分词器进行预处理。使用AutoTokenizer类及其from_pretrained()方法。

from transformers import AutoTokenizer

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)

若要指定我们想要返回的张量类型(PyTorch、TensorFlow 或普通 NumPy),我们使用return_tensors参数

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)

PyTorch 张量的结果:

输出本身是一个包含两个键的字典,input_ids和attention_mask。

{
    '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, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    ])
}

2)Model
模型是预训练的Transformer模型,它接收分词器处理后的输入,并对其进行处理以生成相应的输出。根据不同的任务,可以选择不同的预训练模型,如BERT、GPT等。在Pipeline中,模型会自动从Hugging Face模型库中下载和加载预训练模型。
Transformers 提供了一个AutoModel类,它也有一个from_pretrained()方法:

from transformers import AutoModel

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
model = AutoModel.from_pretrained(checkpoint)

如果我们将预处理过的输入提供给我们的模型,我们可以看到:

outputs = model(**inputs)
print(outputs.last_hidden_state.shape)

# 输出 
# torch.Size([2, 16, 768])

Transformers 中有许多不同的架构可用,每一种架构都围绕着处理特定任务而设计,清单:

Model (retrieve the hidden states)
ForCausalLM
ForMaskedLM
ForMultipleChoice
ForQuestionAnswering
ForSequenceClassification
*ForTokenClassification
and others

3)Post-Processing
后处理步骤用于根据任务的要求对模型的输出进行处理和解释。例如,对于情感分析任务,后处理步骤可能会将模型输出的概率分数转换为标签(如"positive"、"negative");对于问答任务,后处理步骤可能会从模型输出中提取答案。后处理步骤可以根据具体任务的需求进行自定义。
模型最后一层输出的原始非标准化分数。要转换为概率,它们需要经过一个SoftMax层(所有 Transformers 模型都输出 logits,因为用于训练的损耗函数一般会将最后的激活函数(如SoftMax)与实际损耗函数(如交叉熵)融合 。

import torch

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

2. Models

1)创建Transformer
from transformers import BertConfig, BertModel

# Building the config
config = BertConfig()

# Building the model from the config
model = BertModel(config)
2)不同的加载方式
from transformers import BertModel

model = BertModel.from_pretrained("bert-base-cased")
3)保存模型
model.save_pretrained("directory_on_my_computer")
4)使用Transformer model
sequences = ["Hello!", "Cool.", "Nice!"]
encoded_sequences = [
    [101, 7592, 999, 102],
    [101, 4658, 1012, 102],
    [101, 3835, 999, 102],
]

import torch

model_inputs = torch.tensor(encoded_sequences)

3. Tokenizers

1)Loading and saving
from transformers import BertTokenizer

tokenizer = BertTokenizer.from_pretrained("bert-base-cased")
tokenizer("Using a Transformer network is simple")

# 输出
'''
{'input_ids': [101, 7993, 170, 11303, 1200, 2443, 1110, 3014, 102],
 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0],
 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1]}
'''

# 保存
tokenizer.save_pretrained("directory_on_my_computer")
2)Tokenization
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("bert-base-cased")

sequence = "Using a Transformer network is simple"
tokens = tokenizer.tokenize(sequence)

print(tokens) # 输出 : ['Using', 'a', 'transform', '##er', 'network', 'is', 'simple']
#  从token 到输入 ID
ids = tokenizer.convert_tokens_to_ids(tokens)
print(ids) # 输出:[7993, 170, 11303, 1200, 2443, 1110, 3014]
3) Decoding
decoded_string = tokenizer.decode([7993, 170, 11303, 1200, 2443, 1110, 3014])
print(decoded_string) # 输出:'Using a Transformer network is simple'

4. 处理多个序列 Handling multiple sequences

1) 模型需要一批输入 Models expect a batch of inputs

将数字列表转换为张量并将其发送到模型:

import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification

checkpoint = "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)

# 输出
'''
Input IDs: [[ 1045,  1005,  2310,  2042,  3403,  2005,  1037, 17662, 12172,  2607, 2026,  2878,  2166,  1012]]
Logits: [[-2.7276,  2.8789]]
'''
2) 填充输入 Padding the inputs
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>)
'''

5. 总结 Putting it all together

我们已经探索了分词器的工作原理,并研究了分词 tokenizers、转换为输入 ID conversion to input IDs、填充 padding、截断 truncation和注意力掩码 attention masks。Transformers API 可以通过高级函数为我们处理所有这些。

from transformers import AutoTokenizer

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)

sequence = "I've been waiting for a HuggingFace course my whole life."

model_inputs = tokenizer(sequence)

# 可以标记单个序列
sequence = "I've been waiting for a HuggingFace course my whole life."
model_inputs = tokenizer(sequence)

# 还可以一次处理多个序列
sequences = ["I've been waiting for a HuggingFace course my whole life.", "So have I!"]
model_inputs = tokenizer(sequences)

# 可以根据几个目标进行填充
# Will pad the sequences up to the maximum sequence length
model_inputs = tokenizer(sequences, padding="longest")

# Will pad the sequences up to the model max length
# (512 for BERT or DistilBERT)
model_inputs = tokenizer(sequences, padding="max_length")

# Will pad the sequences up to the specified max length
model_inputs = tokenizer(sequences, padding="max_length", max_length=8)

# 还可以截断序列
sequences = ["I've been waiting for a HuggingFace course my whole life.", "So have I!"]

# Will truncate the sequences that are longer than the model max length
# (512 for BERT or DistilBERT)
model_inputs = tokenizer(sequences, truncation=True)

# Will truncate the sequences that are longer than the specified max length
model_inputs = tokenizer(sequences, max_length=8, truncation=True)

# 可以处理到特定框架张量的转换,然后可以将其直接发送到模型。
sequences = ["I've been waiting for a HuggingFace course my whole life.", "So have I!"]

# Returns PyTorch tensors
model_inputs = tokenizer(sequences, padding=True, return_tensors="pt")

# Returns TensorFlow tensors
model_inputs = tokenizer(sequences, padding=True, return_tensors="tf")

# Returns NumPy arrays
model_inputs = tokenizer(sequences, padding=True, return_tensors="np")

Special tokens

分词器在开头添加特殊词[CLS],在结尾添加特殊词[SEP]。

sequence = "I've been waiting for a HuggingFace course my whole life."

model_inputs = tokenizer(sequence)
print(model_inputs["input_ids"])

tokens = tokenizer.tokenize(sequence)
ids = tokenizer.convert_tokens_to_ids(tokens)
print(ids)

# 输出
'''
[101, 1045, 1005, 2310, 2042, 3403, 2005, 1037, 17662, 12172, 2607, 2026, 2878, 2166, 1012, 102]
[1045, 1005, 2310, 2042, 3403, 2005, 1037, 17662, 12172, 2607, 2026, 2878, 2166, 1012]
'''

print(tokenizer.decode(model_inputs["input_ids"]))
print(tokenizer.decode(ids))

# 输出
'''
"[CLS] i've been waiting for a huggingface course my whole life. [SEP]"
"i've been waiting for a huggingface course my whole life."
'''

# 总结:从分词器到模型
import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification

checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
tokenizer = AutoTokenizer.from_pretrained(checkpoint)
model = AutoModelForSequenceClassification.from_pretrained(checkpoint)
sequences = ["I've been waiting for a HuggingFace course my whole life.", "So have I!"]

tokens = tokenizer(sequences, padding=True, truncation=True, return_tensors="pt")
output = model(**tokens)

本节测试:Transformer models - Hugging Face Course

回复

举报

全部回复
暂无回帖,快来参与回复吧
云天徽上
超级版主
主题 71
回复 1
粉丝 0