LLM 大语言模型实战 (七)-深入解读 Hugging Face 开源库 Transformers

一、区分Transformers 库和 Transformer 概念

刚开始学习 Transformers 的同学,可能会将两者的概念混淆,即 Hugging Face 的 Transformers 库和 大模型的 Transformer 架构/结构(输入、编解码器、多头注意力等)有什么区别或异同点,是同一个吗?请详细介绍

Hugging Face 的 Transformers 库Transformer 架构/结构 是相关联但不同的概念。简单来说:

  • Transformers 库 是一个工具库,用于实现和应用基于 Transformer 架构 的模型。
  • Transformer 架构/结构 是一种神经网络模型,用于处理序列数据,广泛应用于自然语言处理(NLP)和其他领域。

接下来,我将详细介绍二者的异同点。


1. Hugging Face Transformers 库

Hugging Face 的 Transformers 库 是一个开源库,旨在简化基于 Transformer 模型的预训练、微调和推理操作。它是一个专注于自然语言处理任务的工具,涵盖了大部分的预训练模型,如 BERT、GPT、T5 等。该库的主要功能是让用户快速应用这些模型并执行 NLP 任务。

主要特征:

  • 提供多种预训练模型:Hugging Face 的 Transformers 库提供了许多预训练好的模型,比如 BERT、GPT、T5、RoBERTa、BART 等。用户可以快速加载这些模型,并用于特定的 NLP 任务(如文本分类、翻译、问答等)。

  • 简化的接口:库提供了便捷的 API,让用户可以快速地分词、加载模型、推理和微调。只需要几行代码,就可以在自己的任务上使用预训练模型。

  • 任务支持:它可以支持多种自然语言处理任务,例如:

    • 文本分类
    • 文本生成
    • 机器翻译
    • 问答系统
    • 文本摘要
  • 跨框架支持:库支持两大主流深度学习框架:PyTorchTensorFlow

示例代码:

from transformers import BertTokenizer, BertModel

# 加载预训练的 BERT 模型和分词器
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained('bert-base-uncased')

# 输入文本并进行分词
inputs = tokenizer("Hello, how are you?", return_tensors="pt")
# 通过模型进行推理
outputs = model(**inputs)

2. Transformer 架构/结构

Transformer 架构 是一种神经网络模型,最早由 Vaswani 等人在 2017 年提出,目的是通过并行化和自注意力机制来解决序列数据的建模问题。与传统的 RNN 或 LSTM 不同,Transformer 架构通过自注意力机制多头注意力机制,可以更好地处理长距离依赖问题,并能并行计算。

主要特征:

  • 编码器-解码器结构:原始的 Transformer 架构由两个部分组成:

    • 编码器(Encoder):处理输入序列,将其转换为一组隐藏表示。
    • 解码器(Decoder):根据编码器输出的隐藏表示生成目标序列。

    这种结构最适合翻译类任务。

  • 自注意力机制(Self-Attention):Transformer 的核心是自注意力机制,它能捕捉输入序列中每个元素与其他元素之间的关系。通过查询(Query)、键(Key)和值(Value)的计算,模型能够动态地分配每个元素的权重,生成更有效的表示。

  • 多头注意力(Multi-Head Attention):在自注意力机制中,Transformer 使用了多头注意力机制,将输入序列映射到多个不同的注意力空间,并并行地计算不同的注意力权重,从多个角度理解序列中的信息。

  • 位置嵌入(Positional Embedding):Transformer 本质上是一个不依赖序列顺序的架构,因此需要加入位置信息,帮助模型理解词与词之间的相对顺序。

Transformer 架构的典型结构:

[Input] -> [Embedding] -> [Positional Encoding] -> [Multi-Head Attention] -> [Feed Forward Network] -> [Output]

3. 异同点分析

相同点

  • 基于同一架构:Hugging Face 的 Transformers 库实现了多种基于 Transformer 架构的模型。无论是 BERT、GPT,还是 T5、BART,它们的底层结构都是基于 Transformer 的编码器或解码器模块,依赖自注意力机制。

  • Attention 机制:无论是在 Transformer 架构还是 Hugging Face 库中,核心的计算部分都是自注意力和多头注意力机制。这是它们都使用的基本机制,用于学习序列中元素之间的关系。

  • 输入和输出处理:两者都依赖于词嵌入(Token Embeddings)和位置嵌入(Positional Embeddings)来表示序列数据,并将其输入到 Transformer 模型中。

不同点

  • 目标和功能

    • Transformers 架构:指的是一种网络结构,它是一个广义的神经网络框架,理论上可以用于多种任务,如自然语言处理、语音处理、图像处理等。其提出的目的是通过自注意力机制更有效地建模序列依赖关系。
    • Hugging Face Transformers 库:是实现和使用 Transformer 模型的一个工具库。它不仅仅是对 Transformer 架构的实现,还包含了许多预训练好的大模型,简化了模型的加载、训练、微调和推理过程。
  • 任务类型

    • Transformer 架构:在理论上是通用的,可以用于各种需要处理序列数据的任务(如 NLP、语音、图像等),不仅限于语言模型。
    • Hugging Face Transformers 库:主要集中在 NLP 任务,虽然它已经扩展到图像处理任务,但其核心功能是为自然语言任务提供预训练模型。
  • 使用范围

    • Transformer 架构:定义了编码器-解码器、自注意力、多头注意力等基础架构,并没有固定实现或库,开发者可以根据需要自定义实现。
    • Hugging Face Transformers 库:提供了具体的实现,用户不需要自己编写底层代码,可以直接使用预训练模型和分词器,大大简化了开发流程。

总结

  • Transformers 架构 是一种理论上的模型设计,最早用于机器翻译任务,现已应用于广泛的 NLP 和其他序列任务。它的核心机制是自注意力和多头注意力。

  • Hugging Face Transformers 库 是基于 Transformer 架构的实现工具,提供了多种预训练模型以及便捷的接口,使得用户可以轻松应用这些大模型。虽然 Hugging Face 的库是基于 Transformer 架构的,但它更专注于实际应用和提供预训练模型。

在实际工作中,Hugging Face 的 Transformers 库是对 Transformer 架构的高级封装和应用,是研究者和开发者快速使用 Transformer 模型的便捷工具。

二、安装

mkdir ~/myenv
cd myenv

# 创建虚拟路径
python -m venv .env

# 在 Linux 和 MacOs 系统中激活虚拟环境:
source .env/bin/activate

# 现在你可以使用以下命令安装 🤗 Transformers:
pip install transformers

# 最后,运行以下命令以检查 🤗 Transformers 是否已被正确安装。该命令将下载一个预训练模型:
python -c "from transformers import pipeline; print(pipeline('sentiment-analysis')('we love you'))"

运行报错提示:

运行报错提示信息:
(.env) (base) ➜  myenv python -c "from transformers import pipeline; print(pipeline('sentiment-analysis')('we love you'))"

A module that was compiled using NumPy 1.x cannot be run in
NumPy 2.1.1 as it may crash. To support both 1.x and 2.x
versions of NumPy, modules must be compiled with NumPy 2.0.
Some module may need to rebuild instead e.g. with 'pybind11>=2.12'.

If you are a user of the module, the easiest solution will be to
downgrade to 'numpy<2' or try to upgrade the affected module.
We expect that some modules will need time to support NumPy 2.

这个报错是因为当前使用的 numpy 2.1.1 版本与某些依赖 numpy 1.x 编译的模块不兼容。transformers 依赖的某些模块尚未完全支持 numpy 2.x,因此出现了兼容性问题。

# 查看版本
# python -c "import numpy; print(numpy.__version__)"

# 降低版本
pip install numpy==1.24.3

然后再次执行:

(.env) (base) ➜  myenv python -c "from transformers import pipeline; print(pipeline('sentiment-analysis')('we love you'))"
No model was supplied, defaulted to distilbert/distilbert-base-uncased-finetuned-sst-2-english and revision af0f99b (https://huggingface.co/distilbert/distilbert-base-uncased-finetuned-sst-2-english).
Using a pipeline without specifying a model name and revision in production is not recommended.
/Users/kaiyi/myenv/.env/lib/python3.11/site-packages/transformers/tokenization_utils_base.py:1601: FutureWarning: `clean_up_tokenization_spaces` was not set. It will be set to `True` by default. This behavior will be depracted in transformers v4.45, and will be then set to `False` by default. For more details check this issue: https://github.com/huggingface/transformers/issues/31884
  warnings.warn(
Hardware accelerator e.g. GPU is available in the environment, but no `device` argument is passed to the `Pipeline` object. Model will be on CPU.
[{'label': 'POSITIVE', 'score': 0.9998704195022583}]
(.env) (base) ➜  myenv 

缓存设置

预训练模型会被下载并本地缓存到 ~/.cache/huggingface/hub。这是由环境变量 TRANSFORMERS_CACHE 指定的默认目录。在 Windows 上,默认目录为 C:\Users\username\.cache\huggingface\hub。你可以按照不同优先级改变下述环境变量,以指定不同的缓存目录。

(.env) (base) ➜  hub pwd
/Users/kaiyi/.cache/huggingface/hub
(.env) (base) ➜  hub ls -l
total 8
drwxr-xr-x  6 kaiyi  staff  192 Sep 25 10:56 models--distilbert--distilbert-base-uncased-finetuned-sst-2-english
-rw-r--r--  1 kaiyi  staff    1 Sep 24 10:45 version.txt
(.env) (base) ➜  hub 

三、实践

1、语音

from transformers import pipeline
transcriber = pipeline(task="automatic-speech-recognition")
transcriber("https://huggingface.co/datasets/Narsil/asr_dummy/resolve/main/mlk.flac")

# openai 开源的语音文字识别大模型
transcriber = pipeline(model="openai/whisper-large-v2")
transcriber("https://huggingface.co/datasets/Narsil/asr_dummy/resolve/main/mlk.flac")

运行结果:

Due to a bug fix in https://github.com/huggingface/transformers/pull/28687 transcription using a multilingual Whisper will default to language detection followed by transcription instead of translation to English.This might be a breaking change for your use case. If you want to instead always translate your audio to English, make sure to pass `language='en'`.
Passing a tuple of `past_key_values` is deprecated and will be removed in Transformers v4.43.0. You should pass an instance of `EncoderDecoderCache` instead, e.g. `past_key_values=EncoderDecoderCache.from_legacy_cache(past_key_values)`.
The attention mask is not set and cannot be inferred from input because pad token is same as eos token. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
{'text': ' I have a dream that one day this nation will rise up and live out the true meaning of its creed.'}

视觉

多模态流水线

 # transformers 库在处理图片时,需要使用 pytesseract 来进行 OCR(光学字符识别),但当前环境中未安装 pytesseract,因此会抛出该错误。
!pip install pytesseract
!apt-get install tesseract-ocr
# 多模态流水线
from transformers import pipeline

vqa = pipeline(model="impira/layoutlm-document-qa")

output = vqa(
    image="https://huggingface.co/spaces/impira/docquery/resolve/2359223c1837a7587402bda0f2643382a6eefeab/invoice.png",
    question="What is the invoice number?",
)

print(output)

AutoTokenizer

几乎所有的NLP任务都以tokenizer开始。tokenizer将您的输入转换为模型可以处理的格式。

使用 AutoTokenizer.from_pretrained() 加载 tokenizer

from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("google-bert/bert-base-uncased")
sequence = "In a hole in the ground there lived a hobbit."
print(tokenizer(sequence))

{'input_ids': [101, 1999, 1037, 4920, 1999, 1996, 2598, 2045, 2973, 1037, 7570, 10322, 4183, 1012, 102], 
 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}

在这个例子中,AutoTokenizer 是从 Hugging Face 的 transformers 库中导入的,用于对文本进行分词,并将其转换为模型可以处理的数值形式(张量)。下面对 tokenizer(sequence) 的输出结果进行解释:

  1. input_ids:
    这是将输入文本分词并映射到词汇表中的 ID 的序列。每个标记(token)都对应于词汇表中的一个唯一 ID。这些 ID 是模型能够理解的数字。具体的映射为:

    • 101 是表示序列开始的特殊标记 [CLS],它在 BERT 模型中用于标记序列的开头。
    • 1999 是 "in" 的 ID。
    • 1037 是 "a" 的 ID。
    • 4920 是 "hole" 的 ID。
    • 1999 是 "in" 的 ID。
    • 1996 是 "the" 的 ID。
    • 2598 是 "ground" 的 ID。
    • 2045 是 "there" 的 ID。
    • 2973 是 "lived" 的 ID。
    • 1037 是 "a" 的 ID。
    • 7570 是 "hobbit" 的 ID。
    • 10322 是 "hobbit" 的标记在词汇表中的 ID(经过词汇分割,"hobbit" 被视为单一标记)。
    • 4183 是表示句子的结束标记 [SEP],这个标记用于模型区分不同句子。
    • 1012 是句子的终止符号(句号)的 ID。
    • 102 是结束标记。
  2. token_type_ids:
    这是指示标记属于哪个句子的 ID。当使用 BERT 进行句子对任务时,token_type_ids 用于区分第一句和第二句的标记。0 表示该标记属于第一个句子(在这个例子中只有一个句子,所以全为 0)。

  3. attention_mask:
    这是一个与 input_ids 大小相同的掩码,值为 1 的地方表示模型应该关注这些标记,值为 0 的地方表示这些标记是填充的、无需关注。在本例中,所有的标记都有意义,因此 attention_mask 全为 1

总结:

  • input_ids 是将输入文本转换为模型词汇表中相应 ID 的序列;
  • token_type_ids 用于区分不同的句子;
  • attention_mask 用于告诉模型哪些标记是需要注意的,哪些可以忽略。

相关文章:
Hugging Face | 🤗 Transformers简介
huggingface/transformers
Huggingface 超详细介绍
图解transformer架构 | illustrated-transformer
CSDN | Transformer通俗笔记:从Word2Vec、Seq2Seq逐步理解到GPT、BERT
集智斑图 | Transformer通俗笔记:从Word2Vec、Seq2Seq到GPT、BERT

为者常成,行者常至