Pipeline推理¶
pipeline() 让使用 🤗 Hugging Face Hub 上的任何模型进行任何语言、计算机视觉、语音以及多模态任务的推理都变得非常简单。
即使你对特定的模态没有经验,或者不熟悉模型的源码,你仍然可以使用pipeline()进行推理!
本教程说明:
- 如何使用 pipeline() 进行推理。
- 如何使用特定的 tokenizer(分词器) 或 model(模型)。
- 如何使用 pipeline() 进行音频、视觉和多模态任务的推理。
请查看pipeline()文档以获取已支持的任务和可用参数的完整列表。
Pipeline使用¶
虽然每种任务都有一个关联的 pipeline,但我们可以使用通用的 pipeline() 方法,其中包含所有特定任务的 pipelines,能够根据任务类型自动加载一个默认模型和一个能够进行任务推理的预处理类。
让我们以使用 pipeline() 进行自动语音识别(ASR)或语音转文本为例。
- 首先,创建一个 pipeline() 并指定推理任务:
from transformers import pipeline
transcriber = pipeline(task="automatic-speech-recognition", device=0) # 任务:自动语音识别(ASR)
- 将你的输入传递给 pipeline()。对于语音识别,通常是输入一个音频文件:
transcriber("../../resources/speech/mlk.flac")
- 如果你在 MAC OS 中运行,可能会遇到错误信息 "ffmpeg was not found but is required to load audio files from filename"。这表示你的环境中缺少
ffmpeg,这是一个用于处理音频和视频文件的强大工具。在 macOS 上,你可以使用 Homebrew 来安装 ffmpeg。
brew install ffmpeg
如果结果不符合你的预期,还可以在 Hub 上查看一些最受欢迎的自动语音识别模型,看看是否可以获得更好的转录结果。
让我们尝试来自 OpenAI 的 Whisper large-v2 模型。Whisperb 比 Wav2Vec2 晚2年发布,使用接近10倍的数据进行了训练。因此,它在大多数下游基准测试上击败了 Wav2Vec2。 它还具有预测标点和大小写的附加优势,而 Wav2Vec2 则无法实现这些功能。
让我们在这里尝试一下,看看它的表现如何:
transcriber = pipeline(task="automatic-speech-recognition", model="openai/whisper-large-v2")
transcriber("../../resources/speech/mlk.flac")
如果你有多个输入,可以将输入作为列表传递:
transcriber(
[
"../../resources/speech/mlk.flac",
"../../resources/speech/1.flac",
]
)
从一个模型切换到另一个模型非常琐碎的过程,但使用 Pipelines 能够非常迅速的切换模型,所以它非常适合用于测试。
但是,通过一些方法还可以将 Pipelines 用于大型工作负载而不仅仅是测试。详细请查看以下指南,深入探讨如何迭代整个数据集或在 Web 服务器中使用 Pipelines:
参数¶
pipeline() 支持了许多参数;有些是适用于特定任务的,有些则是适用于所有的 pipeline。通常情况下,你可以在任何地方指定对应的参数:
transcriber = pipeline(model="openai/whisper-large-v2", my_parameter=1)
out = transcriber(...) # 这将使用 `my_parameter=1`。
out = transcriber(..., my_parameter=2) # 这将覆盖并使用 `my_parameter=2`。
out = transcriber(...) # 这将返回到使用 `my_parameter=1`。
让我们查看其中的三个重要参数:
设备¶
如果你设置 device=n,pipeline 会自动将模型加载到指定的设备上(包括存储模型的权重)。支持 PyTorch 或 Tensorflow。
transcriber = pipeline(model="openai/whisper-large-v2", device=0)
如果你使用的是 PyTorch ,且觉得模型对于单个GPU来说过于庞大,则可以设置 device_map="auto" 使其自动确定如何加载和存储模型的权重。使用 device_map 参数需要安装 🤗 Accelerate 软件包:
pip install --upgrade accelerate
以下代码会自动在各个设备上加载和存储模型权重:
transcriber = pipeline(model="openai/whisper-large-v2", device_map="auto")
请注意,如果设置了 device_map="auto",在实例化 pipeline 时则不需要设置 device=n 参数,否则可能会遇到一些意外的状况!
import os
audio_filenames = [os.path.join('../../resources/speech', f"{i}.flac") for i in range(1, 5)]
transcriber = pipeline(model="openai/whisper-large-v2", device=0, batch_size=2)
texts = transcriber(audio_filenames)
以上代码会在提供的4个音频文件上运行 pipeline,设置 batch_size=2 表示 pipeline 会将它们以每2个为一组的批次传递给模型(若模型加载在GPU上,此时批处理可能更有作用),不需要编写额外的代码。
输出的结果会始终与没有批处理时收到的结果相一致,因为批量推理只是一种帮助你更快地运行 pipeline 的方式,你可以将它理解为是 pipeline 的带宽大小。
同时,使用 pipeline() 能够帮助我们减轻工作量,降低批处理的复杂性。因为对于某些 pipeline ,需要将单个项目(如长音频文件)分成多个部分后才能供模型处理。pipeline() 会在需要时自动执行 chunk batching(分块处理)。
任务特定参数¶
transformers 为所有任务的 pipeline 都提供了特定的参数,这些参数使得 pipeline 更具灵活性,能够帮助你更好地完成工作。
例如,transformers.AutomaticSpeechRecognitionPipeline.call() 方法就具有一个 return_timestamps 参数,能够在模型推断出文本的同时输出各个句子发音的时间戳,对于需要添加字幕的视频很有帮助:
transcriber = pipeline(model="openai/whisper-large-v2", return_timestamps=True)
transcriber("https://huggingface.co/datasets/Narsil/asr_dummy/resolve/main/mlk.flac")
每个任务都有许多可用的参数,因此请查看每个任务的API参考。
例如,在为整部电影或长达一小时的视频添加字幕时,需要模型处理非常长的音频文件,但这通常是模型无法单独处理的,可以通过AutomaticSpeechRecognitionPipeline 设置 chunk_length_s 参数来控制音频处理的分块长度,这非常有帮助:
transcriber = pipeline(model="openai/whisper-large-v2", chunk_length_s=30, return_timestamps=True)
transcriber("https://huggingface.co/datasets/sanchit-gandhi/librispeech_long/resolve/main/audio.wav")
如果你找不到任何一个有帮助的参数,欢迎提出请求!
在数据集上使用 pipelines¶
pipelines 也可以对大型数据集进行推理。
yield 在Python中是一个特殊的标识符,用于将函数转换为生成器(迭代器)。生成器可以一次生成并返回一个值,而不是一次性返回所有值,从而节省内存。
建议使用生成器来完成这一任务,这是最简单的方法:
def data():
for i in range(1000):
yield f"My example {i}"
pipe = pipeline(model="openai-community/gpt2", device=0)
generated_characters = 0
for out in pipe(data()):
generated_characters += len(out[0]["generated_text"])
pipelines 会自动将生成器 data() 识别输入为可迭代对象,并在GPU上处理数据的同时开始获取数据(在底层使用DataLoader)。这一点非常重要,因为你不必为整个数据集分配内存,可以尽可能快地将数据传送到GPU。
由于批处理可以加速处理,因此在这里尝试调整 batch_size 参数可能会很有用。
迭代数据集的最简单方法就是从🤗 (Datasets)[https://github.com/huggingface/datasets/] 中加载数据集:
# KeyDataset 是一个实用工具,它支持从 datasets 库中的数据集中提取特定的字段(或键)传递给 pipelines。
from transformers.pipelines.pt_utils import KeyDataset
from datasets import load_dataset
pipe = pipeline(model="hf-internal-testing/tiny-random-wav2vec2", device=0)
dataset = load_dataset("hf-internal-testing/librispeech_asr_dummy", "clean", split="validation[:10]")
for out in pipe(KeyDataset(dataset, "audio")): # KeyDataset(dataset, "audio") 表示从 dataset 中提取键为 "audio" 的数据。
print(out)
在Web服务器上使用 pipelines¶
视觉任务 pipeline()¶
对于不同视觉任务的 pipeline() 调用方式都非常相似,指定视觉任务模型并将图像传递给分类器。
输入的图像可以是链接、本地路径或base64编码的图像。例如,下面显示的是哪种品种的猫?

from transformers import pipeline
vision_classifier = pipeline(model="google/vit-base-patch16-224", device=0)
preds = vision_classifier(
images="../../resources/images/pipeline-cat-chonk.png"
)
preds = [{"score": round(pred["score"], 4), "label": pred["label"]} for pred in preds]
preds
输出结果解释
模型的输出结果 preds 是一个列表,每个元素包含两个键:score 和 label。
- score:表示模型预测该类别对应的置信分数,范围通常在0到1之间,值越接近1表示模型越确信该类别。
- label:表示预测的类别标签。
自然语言处理任务 pipeline()¶
对于不同NLP任务的 pipeline() 调用方式都非常相似,主要区别在于任务类型和模型的指定。
from transformers import pipeline
# `facebook/bart-large-mnli`是一个`zero-shot-classification`模型,能够在没有针对特定类别进行专门训练的情况下,对文本进行灵活的分类。
classifier = pipeline(model="facebook/bart-large-mnli", device=0)
classifier(
"I have a problem with my iphone that needs to be resolved asap!!",
candidate_labels=["urgent", "not urgent", "phone", "tablet", "computer"],# 它能够对文本内容进行分类,你可以自由地定义任何标签作为候选类别。
)
# 模型的输出通常会包含每个候选标签的置信分数,表示文本属于该标签的可能性。
多模态 pipeline()¶
pipeline() 支持多模态任务的调用。
对于视觉问题回答任务(VQA),pipeline() 结合了文本和图像,使得可以处理任何图像和任何关于该图像的问题。
例如,你想提问关于该图像的问题:
:
要运行下面的示例,除了安装🤗 Transformers 之外,还需要安装 pytesseract 。
Mac OS
brew install tesseract
Windows
Tesseract installer for Windows
Python
pip install pytesseract
from transformers import pipeline
vqa = pipeline(model="impira/layoutlm-document-qa", device=0)
output = vqa(
image="../../resources/images/invoice.png",
question="What is the invoice number?",
)
output[0]["score"] = round(output[0]["score"], 3)
output
在大模型上使用🤗 accelerate 和 pipeline :¶
你可以轻松地使用 🤗 accelerate 在大模型上运行 pipeline!
首先确保你已经使用 pip install accelerate 安装了 accelerate。
首先使用 device_map="auto" 加载你的模型!我们将在示例中使用模型 facebook/opt-1.3b。
device_map="auto"的作用
- 自动设备分配:
- 当你设置device_map="auto"时,transformers库会自动检测你当前的硬件配置(包括CPU和GPU的数量及内存大小)。
- 根据检测到的硬件配置,它会智能地将模型的不同层分配到不同的设备上。例如,如果有一个大型模型和一个GPU,它可能会将模型的一部分放在GPU上,另一部分放在CPU上,以避免内存溢出。
- 优化内存使用:
- 通过智能分配,可以最大限度地利用可用的硬件资源,避免单个设备(如单个GPU)因内存不足而无法加载整个模型。
- 这对于处理像
facebook/opt-1.3b这样的大型模型尤为重要,因为这些模型可能需要大量的内存。
- 提高计算效率: 自动设备分配不仅优化了内存使用,还可以提高计算效率。例如,将计算密集的部分放在GPU上,而将其他部分放在CPU上,可以充分利用不同设备的计算能力。
# pip install accelerate
try:
import accelerate
except ImportError:
raise ImportError("'accelerate' could not be resolved. Please install it by 'pip install accelerate'.")
import torch
from transformers import pipeline
pipe = pipeline(model="facebook/opt-1.3b", torch_dtype=torch.bfloat16, device_map="auto")
output = pipe("This is a cool example!", do_sample=True, top_p=0.95)
如果安装 bitsandbytes 可以通过添加参数 load_in_8bit=True 以8位精度加载模型。
load_in_8bit=True是一个用于模型加载的参数,它指示 transformers 库以8位精度加载模型(而不是标准的16位或32位精度)。这个参数通常与bitsandbytes库结合使用,以实现模型的量化,从而减少内存占用和提高推理速度。虽然8位量化通常会保留模型的绝大部分性能,但在某些情况下可能会略微降低模型的准确率。
# pip install accelerate
try:
import accelerate
except ImportError:
raise ImportError("'accelerate' could not be resolved. Please install it by 'pip install accelerate'.")
# pip install bitsandbytes
try:
import bitsandbytes
except ImportError:
raise ImportError("'bitsandbytes' could not be resolved. Please install it by 'pip install bitsandbytes'.")
import torch
from transformers import pipeline
pipe = pipeline(model="facebook/opt-1.3b", device_map="auto", model_kwargs={"load_in_8bit": True})
# 使用随机抽样
output_sample = pipe("This is a cool example!", do_sample=True, top_p=0.95)
print("With do_sample=True:", output_sample[0]['generated_text'])
# 不使用随机抽样
output_greedy = pipe("This is a cool example!", do_sample=False)
print("With do_sample=False:", output_greedy[0]['generated_text'])
do_sample 随机抽样
do_sample参数决定了模型在生成下一个token时是选择概率最高的token,还是从概率分布中随机抽取一个token。
- 当
do_sample=True时,模型会在每个时间步根据概率分布随机选择下一个token。这种方法可以增加生成文本的多样性和创造性,使其看起来更自然、更不重复。 - 当
do_sample=False时,模型始终选择概率最高的token作为下一个token。这种方法生成的文本通常更保守、更可预测,但可能会显得单调、缺乏多样性。
参数组合
do_sample通常与top_k和top_p(也称为nucleus sampling)等参数结合使用,以进一步控制抽样过程。
top_k:与do_sample=True结合使用时,表示从概率最高的 k 个 token 中进行随机抽样。top_p:与do_sample=True结合使用时,表示从累积概率超过 p 的 token 集合中进行随机抽样。
在Hugging Face的文档中,"checkpoint" 是一个泛指,代表你选择的预训练模型。在代码中,你通过替换 "model" 参数的值来选择不同的模型。
请注意,你可以将 checkpoint 替换为任何支持大模型加载的 Hugging Face 模型,比如 BLOOM。只需将模型 facebook/opt-1.3b 替换为 bigscience/bloom-1b1 即可。
import torch
from transformers import pipeline
# 替换模型名称为BLOOM模型
model_name = "bigscience/bloom-1b1"
# 创建文本生成 pipeline
pipe = pipeline(
model=model_name,
device_map="auto",
model_kwargs={"load_in_8bit": True}
)
# 生成文本
output = pipe(
"This is a cool example!",
do_sample=True,
top_p=0.95
)
# 打印生成的文本
print(output[0]['generated_text'])