Hugging Face系列2:详细剖析Hugging Face网站资源——实战六类开源库

Hugging Face系列2:详细剖析Hugging Face网站资源——实战六类开源库

  • 前言
  • 本篇摘要
  • 2. Hugging Face开源库
    • 2.1 transformers
      • 2.1.1 简介
      • 2.1.2 实战
        • 1. 文本分类
        • 2. 图像识别
        • 3. 在Pytorch和TensorFlow中使用pipeline
    • 2.2 diffusers
      • 2.2.1 简介
      • 2.2.2 实战
        • 1. 管线
        • 2. 模型和调度器
    • 2.3 datasets
      • 2.3.1 简介
      • 2.3.2 实战
    • 2.4 PEFT
      • 2.4.1 简介
      • 2.4.2 实战
        • 1. peft模型
        • 2. 新旧模型结构对比
        • 3. PEFT模型推理
    • 2.5 accelerate
      • 2.5.1 简介
      • 2.5.2 实战
        • 1. 与pytorch融合
        • 2. 命令行accelerate config&launch
        • 3. DeepSpeed
        • 4. notebook_launcher
    • 2.6 optimum
      • 2.6.1 简介
      • 2.6.2 实战
        • 1. ONNX&ONNX Runtime
        • 2. 加速推理
        • 3. 加速训练
  • 参考文献

前言

本系列文章旨在全面系统的介绍Hugging Face,让小白也能熟练使用Hugging Face上的各种开源资源,并上手创建自己的第一个Space App,在本地加载Hugging Face管线训练自己的第一个模型,并使用模型生成采样数据,同时详细解决部署中出现的各种问题。后续文章会分别介绍采样器及其加速、显示分类器引导扩散模型、CLIP多模态图像引导生成、DDMI反转及控制类大模型ControlNet等,根据反馈情况可能再增加最底层的逻辑公式和从零开始训练LLM等,让您从原理到实践彻底搞懂扩散模型和大语言模型。欢迎点赞评论、收藏和关注。

本系列文章如下:

  1. 《详细剖析Hugging Face网站资源——models/datasets/spaces》:全面系统的介绍Hugging Face资源;
  2. 《详细剖析Hugging Face网站资源——实战六类开源库》
  3. 《从0到1:使用Hugging Face管线加载Diffusion模型生成第一张图像》:在本地加载Hugging Face管线训练自己的第一个模型,并使用模型生成采样数据,同时详细解决部署中出现的各种问题。

本篇摘要

本篇主要介绍Hugging Face。Hugging Face是一个人工智能的开源社区,是相关从业者协作和交流的平台。它的核心产品是Hugging Face Hub,这是一个基于Git进行版本管理的存储库,截至2024年5月,已托管了65万个模型、14.5万个数据集以及超过17万个Space应用。另外,Hugging Face还开源了一系列的机器学习库如Transformers、Datasets和Diffusers等,以及界面演示工具Gradio。此外,Hugging Face设计开发了很多学习资源,比如与NLP(大语言模型)、扩散模型及深度强化学习等相关课程。最后介绍一些供大家交流学习的平台。为了更有趣,本篇介绍了大量有趣的Spaces应用,比如换装IDM-VTON、灯光特效IC-Light、LLM性能排行Artificial Analysis LLM Performance Leaderboard和自己部署的文生图模型stable-diffusion-xl-base-1.0、对图片精细化的stable-diffusion-xl-refiner-1.0等。只要读者认真按着文章操作,上述操作都可自己实现。下面对以上内容逐一介绍。

2. Hugging Face开源库

除了Hugging Face Hub提供的models、datasets和spaces,Hugging Face还在GitHub上开源了一系列的机器学习库和工具。在GitHub的Hugging Face组织页面,其置顶了一些开源代码仓库,包括transformers、diffusers、datasets、peft、accelerate以及optimum,如下图所示。本篇逐一详细介绍并给出对应的实战用例,方便读者更直观的理解和应用。

在这里插入图片描述

2.1 transformers

2.1.1 简介

transformers 提供了数以千计的可执行不同任务的SOTA1预训练模型,这些任务包括(1)支持 100 多种语言的文本分类、信息抽取、问答、摘要、翻译、文本生成的文本任务;(2)用于图像分类,目标检测和分割等图像任务;(3)用于语音识别和音频分类等音频任务。Transformer模型还可以在几种模式的组合上执行任务,例如表格问答、光学字符识别、从扫描文档中提取信息、视频分类和视觉问答等。

Transformers 提供了便于快速下载和使用的API,让你可以将预训练模型在给定文本、数据集上微调后,通过 model hub 与社区共享;同时,每个定义的 Python 模块均完全独立,方便修改和快速研究实验。Transformers 支持三个最热门的深度学习库: Jax, PyTorch 以及 TensorFlow——并与之无缝整合。你可以直接使用一个框架训练你的模型然后用另一个加载和推理,以支持框架之间的互操作。模型还可以导出成ONNX和TorchScript等格式,以方便在生产环境中部署。

用户可以通过transformers直接测试和使用model hub中的大部分模型,以节省训练时间和资源,降低成本。

2.1.2 实战

Hugging Face提供pipeline API以便在给定的输入(文本、图像、音频等)上使用模型。模型训练期间,管道用预训练模型实现预处理。

在使用任何库之前,需要先安装:

# upgrade参数保证安装最新版
pip install --upgrade XXX

下面看三个例子。

1. 文本分类

使用pipeline实现文本分类:

>>> from transformers import pipeline

# Allocate a pipeline for sentiment-analysis. The second line of code downloads and caches the pretrained model used by the pipeline, while the third evaluates it on the given text.
>>> classifier = pipeline('sentiment-analysis')
>>> classifier('We are very happy to introduce pipeline to the transformers repository.')
[{'label': 'POSITIVE', 'score': 0.9996980428695679}]
2. 图像识别

使用pipeline实现图像识别:

>>> import requests
>>> from PIL import Image
>>> from transformers import pipeline

# Download an image with cute cats
>>> url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/coco_sample.png"
>>> image_data = requests.get(url, stream=True).raw
>>> image = Image.open(image_data)

# Allocate a pipeline for object detection
>>> object_detector = pipeline('object-detection')
>>> object_detector(image)
[{'score': 0.9982201457023621,
  'label': 'remote',
  'box': {'xmin': 40, 'ymin': 70, 'xmax': 175, 'ymax': 117}},
 {'score': 0.9960021376609802,
  'label': 'remote',
  'box': {'xmin': 333, 'ymin': 72, 'xmax': 368, 'ymax': 187}},
 {'score': 0.9954745173454285,
  'label': 'couch',
  'box': {'xmin': 0, 'ymin': 1, 'xmax': 639, 'ymax': 473}},
 {'score': 0.9988006353378296,
  'label': 'cat',
  'box': {'xmin': 13, 'ymin': 52, 'xmax': 314, 'ymax': 470}},
 {'score': 0.9986783862113953,
  'label': 'cat',
  'box': {'xmin': 345, 'ymin': 23, 'xmax': 640, 'ymax': 368}}]
3. 在Pytorch和TensorFlow中使用pipeline

代码如下:

>>> from transformers import AutoTokenizer, AutoModel

>>> tokenizer = AutoTokenizer.from_pretrained("google-bert/bert-base-uncased")
>>> model = AutoModel.from_pretrained("google-bert/bert-base-uncased")

# pytorch uses pt and tensorflow uses tf
>>> inputs = tokenizer("Hello world!", return_tensors="pt")
>>> outputs = model(**inputs)

代码解释:tokenizer负责为预训练模型预处理字符串,并且可指定返回张量格式,然后传入model作训练,产生最终输出。示例代码演示了如何在PyTorch或TensorFlow框架中使用模型,并在新数据集上使用训练API快速微调预处理模型。

2.2 diffusers

2.2.1 简介

diffusers是SOTA预训练扩散模型的首选库,可用于生成图像、音频,甚至分子的3D结构。diffusers是一个模块化工具箱,既可支持简单的推理解决方案,也支持训练自己的扩散模型。diffusers库设计注重可用性而非性能,简单而非简易,可定制化而非抽象。

diffusers提供三个核心组件:1)最先进的扩散管道diffusion pipelines,只需几行代码即可进行推理;2)可互换噪声调度器noise schedulers,可用于调节推理过程中模型生成中的扩散速度和输出质量;3)预训练模型pretrained models可用作构建块,并与调度器相结合,以创建自己的端到端扩散系统。

2.2.2 实战

实战包括管线、模型和调度器。

1. 管线

使用diffusers生成输出非常容易,如文生图,可使用from_pretrained方法加载预训练的扩散模型stable-diffusion:

from diffusers import DiffusionPipeline
import torch

pipeline = DiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5", torch_dtype=torch.float16)
pipeline.to("cuda")
pipeline("An image of a squirrel in Picasso style").images[0]
2. 模型和调度器

还可以深入研究预训练模型和噪声调度器的工具箱,构建自己的扩散系统:

from diffusers import DDPMScheduler, UNet2DModel
from PIL import Image
import torch

scheduler = DDPMScheduler.from_pretrained("google/ddpm-cat-256")
model = UNet2DModel.from_pretrained("google/ddpm-cat-256").to("cuda")
scheduler.set_timesteps(50)

sample_size = model.config.sample_size
noise = torch.randn((1, 3, sample_size, sample_size), device="cuda")
input = noise

for t in scheduler.timesteps:
    with torch.no_grad():
        noisy_residual = model(input, t).sample
        prev_noisy_sample = scheduler.step(noisy_residual, t, input).prev_sample
        input = prev_noisy_sample

image = (input / 2 + 0.5).clamp(0, 1)
image = image.cpu().permute(0, 2, 3, 1).numpy()[0]
image = Image.fromarray((image * 255).round().astype("uint8"))
image

2.3 datasets

2.3.1 简介

datasets是一个轻量级库,旨在让社区轻松添加和共享新的数据集,它提供两个主要功能:

  1. 可用于众多公共数据集的dataloaders:可一行代码下载和预处理HuggingFace Datasets Hub提供的任意数据集,包括图像数据集、音频数据集、467种语言/方言的文本数据集等。示例如squad_dataset=load_dataset(“squad”)。
  2. 高效的数据预处理:可简单、快速和可复制的预处理众多公共数据集及本地的CSV、JSON、text、PNG、JPEG、WAV、MP3、Parquet等格式数据。示例如processed_dataset=dataset.map(process_example)。

此外,datasets还有许多其他有趣的功能:

  1. 适配于大型数据集:datasets将用户从RAM内存限制中解放出来,所有数据集都使用高效的零序列化成本后端(Apache Arrow)进行内存映射。
  2. 智能缓存:重复处理数据无需等待。
  3. 支持轻量快速透明的Python API,Python API还具有多处理器、缓存及内存映射等特性。
  4. 内置支持与NumPy、pandas、PyTorch、TensorFlow 2和JAX进行互操作。
  5. 原生支持音频和图像数据。
  6. 支持启用流模式以节省磁盘空间,可快速开启对数据集进行迭代。

需要指出的是,HuggingFace Datasets源于优秀的TensorFlow数据集的一个分支,两者差异主要是HuggingFace Datasets动态加载python脚本而不是在库中提供、后端序列化基于Apache Arrow而不是TF Records、面向用户的datasets对象(封装了一个内存映射的Arrow表缓存)基于与框架无关的由tf.data的方法激发的数据集类而不是基于tf.data.Dataset。

2.3.2 实战

datasets的API以函数datasets.load_dataset(dataset_name, **kwargs)为中心,该函数用于实例化数据集。
加载文本数据集的示例:

from datasets import load_dataset

# Print all the available datasets
from huggingface_hub import list_datasets
print([dataset.id for dataset in list_datasets()])

# Load a dataset and print the first example in the training set
squad_dataset = load_dataset('squad')
print(squad_dataset['train'][0])

# Process the dataset - add a column with the length of the context texts
dataset_with_length = squad_dataset.map(lambda x: {"length": len(x["context"])})

# Process the dataset - tokenize the context texts (using a tokenizer from the ???? Transformers library)
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained('bert-base-cased')

tokenized_dataset = squad_dataset.map(lambda x: tokenizer(x['context']), batched=True)

当数据集比磁盘空间大,或者不想下载数据时,可以使用流媒体,示例如下:

# If you want to use the dataset immediately and efficiently stream the data as you iterate over the dataset
image_dataset = load_dataset('cifar100', streaming=True)
for example in image_dataset["train"]:
    break

2.4 PEFT

2.4.1 简介

PEFT(Parameter-Efficient Fine-Tuning)即SOTA高效参数微调方法,由于大型模型的参数规模,完全微调模型成本极高,而PEFT仅通过微调少量参数就可以达到完全微调的性能,使型预训练模型有效地适应各种下游应用,显著降低计算和存储成本。

PEFT与Transformers集成,可轻松进行模型训练和推理;与Diffuser集成,可方便地管理不同的适配器;与Accelerate集成,可用于真正大型模型的分布式训练和推理。

提示:(1)PEFT方法如何用于下游各类任务可参考PEFT 组织部分jupyter notebook的演示;(2)查看PEFT API Reference的 Adapters部分,可得到PEFT支持的方法列表。阅读CONCEPTUAL GUIDES部分学习如何使用。如下图:
在这里插入图片描述

2.4.2 实战

实战包括示例、新旧模型对比和模型推理三部分。

1. peft模型

在使用PEFT中方法(如LoRA)训练模型之前,需要通过get_peft_model()将基础模型和PEFT配置包装在一起。

比如下例的bigscience/mt0-large,只需训练完全模型0.19%的参数即可:

from transformers import AutoModelForSeq2SeqLM
from peft import get_peft_config, get_peft_model, LoraConfig, TaskType
model_name_or_path = "bigscience/mt0-large"
tokenizer_name_or_path = "bigscience/mt0-large"

peft_config = LoraConfig(
    task_type=TaskType.SEQ_2_SEQ_LM, inference_mode=False, r=8, lora_alpha=32, lora_dropout=0.1
)

model = AutoModelForSeq2SeqLM.from_pretrained(model_name_or_path)
model_peft = get_peft_model(model, peft_config)
model.print_trainable_parameters()
"trainable params: 2359296 || all params: 1231940608 || trainable%: 0.19151053100118282"
2. 新旧模型结构对比

现在打印出新旧模型作对比,看PEFT到底做了什么。也可参考Spaces空间中使用PEFT的示例,如下:

# 查看peft配置
model.peft_config

PrefixTuningConfig(peft_type=<PeftType.PREFIX_TUNING: 'PREFIX_TUNING'>, base_model_name_or_path='bigscience/mt0-large', 
task_type=<TaskType.SEQ_2_SEQ_LM: 'SEQ_2_SEQ_LM'>, inference_mode=False, num_virtual_tokens=30, token_dim=1024, num_transformer_submodules=1, 
num_attention_heads=16, num_layers=24, encoder_hidden_size=1024, prefix_projection=False)

# 打印旧模型
print(model)
MT5ForConditionalGeneration(
  (shared): Embedding(250112, 1024)
  (encoder): MT5Stack(
    (embed_tokens): Embedding(250112, 1024)
    (block): ModuleList(
      (0): MT5Block(
        (layer): ModuleList(
          (0): MT5LayerSelfAttention(
            (SelfAttention): MT5Attention(
              (q): Linear(in_features=1024, out_features=1024, bias=False)
              (k): Linear(in_features=1024, out_features=1024, bias=False)
              (v): Linear(in_features=1024, out_features=1024, bias=False)
              (o): Linear(in_features=1024, out_features=1024, bias=False)
              (relative_attention_bias): Embedding(32, 16)
            )
            (layer_norm): MT5LayerNorm()
            (dropout): Dropout(p=0.1, inplace=False)
          )
          (1): MT5LayerFF(
            (DenseReluDense): MT5DenseGatedActDense(
              (wi_0): Linear(in_features=1024, out_features=2816, bias=False)
              (wi_1): Linear(in_features=1024, out_features=2816, bias=False)
              (wo): Linear(in_features=2816, out_features=1024, bias=False)
              (dropout): Dropout(p=0.1, inplace=False)
              (act): NewGELUActivation()
            )
            (layer_norm): MT5LayerNorm()
            (dropout): Dropout(p=0.1, inplace=False)
          )
        )
      )
      (1-23): 23 x MT5Block(...)
    (final_layer_norm): MT5LayerNorm()
    (dropout): Dropout(p=0.1, inplace=False)
  )
  (decoder): MT5Stack(
    (embed_tokens): Embedding(250112, 1024)
    (block): ModuleList(
      (0): MT5Block(
        (layer): ModuleList(
          (0): MT5LayerSelfAttention(
            (SelfAttention): MT5Attention(
              (q): Linear(in_features=1024, out_features=1024, bias=False)
              (k): Linear(in_features=1024, out_features=1024, bias=False)
              (v): Linear(in_features=1024, out_features=1024, bias=False)
              (o): Linear(in_features=1024, out_features=1024, bias=False)
              (relative_attention_bias): Embedding(32, 16)
            )
            (layer_norm): MT5LayerNorm()
            (dropout): Dropout(p=0.1, inplace=False)
          )
          (1): MT5LayerCrossAttention(
            (EncDecAttention): MT5Attention(
              (q): Linear(in_features=1024, out_features=1024, bias=False)
              (k): Linear(in_features=1024, out_features=1024, bias=False)
              (v): Linear(in_features=1024, out_features=1024, bias=False)
              (o): Linear(in_features=1024, out_features=1024, bias=False)
            )
            (layer_norm): MT5LayerNorm()
            (dropout): Dropout(p=0.1, inplace=False)
          )
          (2): MT5LayerFF(
            (DenseReluDense): MT5DenseGatedActDense(
              (wi_0): Linear(in_features=1024, out_features=2816, bias=False)
              (wi_1): Linear(in_features=1024, out_features=2816, bias=False)
              (wo): Linear(in_features=2816, out_features=1024, bias=False)
              (dropout): Dropout(p=0.1, inplace=False)
              (act): NewGELUActivation()
            )
            (layer_norm): MT5LayerNorm()
            (dropout): Dropout(p=0.1, inplace=False)
          )
        )
      )
      (1-23): 23 x MT5Block(
        (layer): ModuleList(...)
    (final_layer_norm): MT5LayerNorm()
    (dropout): Dropout(p=0.1, inplace=False)
  )
  (lm_head): Linear(in_features=1024, out_features=250112, bias=False)
)

# 打印peft模型
print(model_peft)
PeftModelForSeq2SeqLM(
  (base_model): IA3Model(
    (model): MT5ForConditionalGeneration(
      (shared): Embedding(250112, 1024)
      (encoder): MT5Stack(
        (embed_tokens): Embedding(250112, 1024)
        (block): ModuleList
上一篇:学习笔记 SD卡(1)


下一篇:交互式流程图组件DHTMLX Diagram v6.0 - 拥有更灵活的高度可定制功能-创建HTML内容