DLAI-HuggingFace-开源模型笔记-全-

DLAI HuggingFace 开源模型笔记(全)

001:课程介绍 🎯

在本课程中,我们将学习如何利用Hugging Face平台上的开源模型,快速构建各种人工智能应用。课程内容涵盖文本、音频和图像处理,并教你如何将这些模型组合起来,实现更复杂的功能。

欢迎来到这门与Hugging Face合作打造的短期课程《拥抱开源模型》。得益于开源软件,如果你想构建一个AI应用,你可以从这里获取一个图像识别组件,从那里获取一个自动语音识别模型,再从其他地方获取一个大型语言模型,然后将它们快速串联起来,构建一个新的应用。

Hugging Face通过让众多开源模型易于获取,极大地改变了AI社区,使得任何人都能轻松做到这一点。这极大地加速了人们构建AI应用的过程。在本课程中,你将直接向Hugging Face团队学习如何做到这一点,并亲自构建很酷的应用,其速度可能比你之前想象的还要快。

例如,你将使用模型进行自动语音识别,将语音转录为文本,同时也会使用文本转语音模型,将文本转换为音频。这些模型与大型语言模型相结合,为你提供了构建自己的语音助手所需的基础模块。

你还会看到如何使用Hugging Face的Transformers库来快速预处理以及后处理机器学习模型的输出。例如,预处理音频,就像在我刚才提到的ASR或TTS示例中控制音频采样率一样,以及预处理或后处理图像和文本等数据。

利用开源组件快速构建应用的理念,已经成为AI应用构建方式的一次范式转变。在本课程中,你将亲自体验如何做到这一点。我很高兴向大家介绍本课程的讲师。

Eunice Valgoar是Hugging Face的一名机器学习工程师,他参与了开源团队的工作,涉足Hugging Face开发的许多开源工具的交集,例如Transformers、参数高效微调和TRL。

Markson同样是Hugging Face的一名机器学习工程师,也是开源团队的一员,他为Transformers库和Ace等库做出了贡献。

Maria haousoverva是Hugging Face的技术团队成员,她领导Hugging Face的教育项目,并致力于跨库协作,使机器学习对每个人来说都更容易上手。

Andrew,我们很高兴能与你和你的团队合作。

首先,你将使用开源大型语言模型创建自己的聊天机器人。你将使用来自Meta的开源大型语言模型,同样的代码也适用于更强大的开源大型语言模型,前提是你拥有更强大的硬件。你将使用开源模型将文本从一种语言翻译成另一种语言、总结文档以及计算句子嵌入,以便比较两个句子之间的相似性。

接下来,你将使用Transformers处理音频。

当你向语音助手询问天气预报时,你认为它可能执行哪些音频任务?它知道在你叫它的名字时被唤醒,这是分类任务。它将你的语音转换为文本来查找你的请求,这是自动语音识别。它向你回复,这是文本转语音。在本课程中,你将分类任意声音、转录语音录音以及从文本生成语音。

Transformers在计算机视觉中的应用非常丰富。你将学习如何检测图像中的物体,并将图像分割成称为语义区域的区域。例如,你可以应用此代码来检测图像中存在一只小狗,并分割出构成小狗耳朵的部分。

在你学会处理文本、音频和图像任务后,你可以将这些模型按顺序组合起来,以处理更复杂的流程。例如,如果你的应用想通过描述图像来帮助有视力障碍的人,你该如何实现?在本课程中,你将应用物体检测来识别图像中的物体,应用图像分类以文本形式描述这些物体,然后应用语音生成来叙述这些物体的名称。

你还会使用一个可以接受多种数据类型作为输入的模型,这些模型被称为多模态模型。例如,你将构建一个视觉问答应用,你可以向模型发送一张图像以及关于该图像的问题,然后你的应用可以根据图像返回该问题的答案。

你还将使用Gradio库将AI应用部署到Hugging Face Spaces上,这样任何人都可以通过互联网进行API调用来使用你的应用执行任务。

当然,所有这些示例的目标不仅仅是让你真正构建这些特定的例子,而是让你了解所有这些基础模块,以便你能够真正将它们组合成自己独特的应用。

许多人共同努力创建了这门课程。我要感谢Hugging Face方面,整个Hugging Face团队对课程内容的审核,以及Hugging Face社区对开源模型的贡献。来自DeepLearning.AI的Eddie Shu也为本课程做出了贡献。

在第一课中,你将学习如何在Hugging Face Hub上浏览数千个模型,为你的任务找到合适的模型,以及如何使用Transformers库中的pipeline对象开始构建你的应用。

这听起来非常令人兴奋。让我们进入下一个视频,开始学习吧。


本节课中,我们一起学习了本课程的整体目标和结构。我们了解到,通过Hugging Face平台,我们可以便捷地获取和使用各种开源AI模型,快速构建从文本处理、语音识别到计算机视觉的多样化应用。课程将引导我们从基础模块学起,最终学会组合这些模块,实现更复杂的多模态应用。

002:模型选择 🎯

在本节课中,我们将学习如何在Hugging Face Hub上从数千个开源模型中,为你的项目找到最合适的模型。我们将了解如何利用任务、语言、许可证等条件筛选模型,并学习如何评估模型的技术细节。

概述

如今,有数千个开源模型可供使用。每周都有许多新模型在Hugging Face Hub上发布。Hugging Face Hub是一个托管模型、数据集和机器学习演示(称为Spaces)的开放平台。那么,如何为你的项目找到所需的模型呢?让我们前往Hugging Face Hub一探究竟。

在模型页面筛选

在模型页面上,你可以找到适用于许多任务的模型。

这里的模型数量可能看起来令人不知所措。开始搜索时,一个好方法是先确定你在机器学习术语中正在处理的任务。在本课程中,你会看到许多任务示例。假设我想进行自动语音识别。

让我们从左侧面板中选择它。仍然有很多模型可供选择,但你可以进一步缩小搜索范围。假设你需要一个转录法语语音的模型。

你可以在这里选择语言。再假设你需要一个具有宽松许可证的模型。所谓宽松,是指允许你将模型用于大多数类型的应用程序(包括商业用途)的许可证。这会大大减少你的选项。

你可以按下载量排序,以找到该任务中常用的模型。或者,如果你想尝试社区最近热议的新模型,可以按趋势排序。

查看模型卡片

在选择一个模型之前,请查看它们的模型卡片。一份编写良好的模型卡片就像是模型的README文件。它包含大量有用信息,例如模型架构、训练方式、存在的局限性等等,正如你在这里看到的。

模型可以拥有不同参数数量的检查点。因此,我们说这种类型的模型有不同的尺寸。检查点指的是已保存的模型,包括预训练权重和所有必要的配置。我们常说加载一个模型,但从技术上讲,是加载一个模型检查点。

有些检查点有数千万个参数,另一些则有十亿或数十亿个参数。根据你的硬件,你可能无法运行最大的检查点。

估算内存需求

让我展示一个我用来估算运行模型所需内存的经验法则。我们转到“文件和版本”页面。

在这里,你可以找到一个名为 pytorch_model.bin 的文件。这个文件存储了模型的训练权重,你可以轻松看到它的大小。

将该大小乘以1.2(换句话说,增加20%),这大致就是你运行此模型所需的内存。

通过任务页面发现模型

现在让我快速展示另一种为任务、数据集或演示寻找模型的方法。让我们转到任务页面。

在这个页面上,你可以了解不同的机器学习任务。让我们选择一个我们感兴趣的任务。再次选择自动语音识别。

在这个页面上,你可以了解任务本身,这是发现你尚未接触过的机器学习任务的好方法。你还可以找到适用于此任务的模型建议、可以使用的数据集,以及可以试用执行此任务的模型的演示。

请注意,OpenAI的Whisper在这里被建议为首选。让我们回到模型页面。

使用Transformers库加载模型

要从Hugging Face Hub加载此模型,你可以使用Transformers库。注意“使用Transformers”按钮。

如果你点击它,你会找到两个有用的代码片段,展示如何加载模型检查点。在本课程中,你将使用 pipeline 对象来处理模型,如第一个示例所示。

pipeline 对象提供了一个高级抽象来解决任务。它还负责复杂的输入预处理,以匹配模型的期望。例如,一些音频模型期望输入音频以对数梅尔频谱图的形式提供。文本通常需要转换为所谓的标记,图像通常需要适当调整大小并进行归一化。使用 pipeline,你无需手动执行任何这些预处理步骤。

总结

现在你已经知道如何为你的任务寻找模型以及在哪里找到 pipeline 代码片段。让我们构建你的第一个应用程序。我们进入下一课。

003:3.nlp.zh - 使用开源模型构建聊天机器人 🤖

在本节课中,我们将学习如何使用 Hugging Face Transformers 库来执行自然语言处理任务。具体来说,我们将构建一个自己的聊天机器人,使用一个由 Meta 开发的开源模型。我们将从了解 NLP 的基本概念开始,逐步学习如何使用 pipeline 函数,并探索如何为不同任务选择合适的模型。


什么是自然语言处理? 📖

上一节我们介绍了课程目标,本节中我们来看看自然语言处理(NLP)的定义。NLP 是一个结合了语言学和机器学习的领域,其核心关注点是与人类语言相关的一切。自 2017 年著名论文《Attention Is All You Need》提出 Transformer 架构以来,该领域取得了显著进展。如今,Transformer 架构已成为许多先进机器学习模型的核心。

在本课程中,我们将使用 Transformers 库,特别是其中的 pipeline 函数。

开始使用 Transformers 库 🚀

首先,我们需要导入必要的函数。如下所示,我们从 transformers 库中导入了 pipeline 函数。

from transformers import pipeline

对于本课程环境,相关库已预先安装。如果你在自己的机器上运行,可以通过运行以下命令来安装 Transformers 库(此处无需执行,故注释掉):

# pip install transformers

现在,我们已经具备了创建聊天机器人所需的一切。

创建聊天机器人 💬

以下是创建聊天机器人的步骤:

我们使用来自 Facebook(现 Meta)的 Blenderbot 模型创建了一个对话管道。

我们选择这个模型的主要原因是它体积小且性能良好,仅需 1.6 GB 内存即可加载。由于本课程环境只有 4 GB 可用内存,我们无法使用 Llama 等其他大型模型。

chatbot = pipeline(“conversational”, model=“facebook/blenderbot-400M-distill”)

pipeline 函数的第一个参数是任务类型,这里我们传入 “conversational”。第二个参数是需要加载的模型,我们指定了 Facebook 的模型。

现在聊天机器人已加载完成,让我们传递一条用户消息。我们将询问聊天机器人:“冬天有哪些有趣的活动可以做?”

为了将用户消息传递给聊天机器人,我们首先需要将其放入一个 Conversation 对象中。因此,让我们导入这个对象。

from transformers import Conversation

你只需要将用户消息放入 Conversation 对象中,然后将整个对话对象传递给聊天机器人。

conversation = Conversation(“What are some fun activities I can do in the winter?”)
conversation = chatbot(conversation)
print(conversation.generated_responses[-1])

如你所见,助手回复道:“我喜欢滑雪和单板滑雪。你冬天喜欢做什么?” 你可以自由更改用户消息,例如询问关于生日的点子、夏天可以做的事情,或者任何你想问聊天机器人的问题。

探索其他 NLP 任务 🔍

现在让我们退一步,回顾一下你可以使用开源模型执行的其他 NLP 任务。你将看到如何搜索 Hugging Face Hub 来为各种任务寻找合适的模型。

NLP 有许多应用。你一定听说过 OpenAI 的 ChatGPT,或者其开源替代品 Hugging Chat,后者允许用户选择任何开源语言模型(如 Llama 2 或 Mistral)进行对话。NLP 也存在于我们日常使用的许多工具中,例如文档中的自动补全、翻译工具,甚至垃圾邮件过滤器。

NLP 包含许多任务。在接下来的几节课中,你将学习其中几个,但也可以自行尝试其余任务。

以下是几个主要的 NLP 任务:

  • 文本生成:用于构建聊天机器人的任务。
  • 句子相似度:判断两个句子的语义相似度。
  • 文本摘要:将长文档浓缩为简短摘要。
  • 机器翻译:将文本从一种语言翻译成另一种语言。

如何选择合适的模型? 🧐

一个关键问题仍然存在:我们应该选择哪个模型?有如此多的开源模型可供选择。

要浏览模型,你可以使用 Hugging Face Hub。我将展示我如何为我们的对话管道选择 Facebook 的模型。

  1. 访问 Hugging Face Hub 的模型板块。
  2. 添加过滤器,选择“对话”任务。对话任务是指根据提示生成相关、连贯且知识丰富的对话文本,该模型可用于聊天机器人和语音助手。
  3. 默认情况下,模型按趋势排序。我们可以将其改为“最多点赞”。
  4. 可以看到有很多不同的模型。由于课程环境只有 4 GB 内存,我们需要选择一个较小的模型。
  5. 第二个模型(facebook/blenderbot-400M-distill)似乎是一个很好的选择,因为它只有 4 亿参数,体积相当小。我们看到它被下载了很多次,并且有很多点赞。
  6. 我们可以点击进入“文件”选项卡,看到模型大小仅为 730 MB。
  7. 点击“使用 Transformers”可以学习如何加载它。这个命令对你来说应该很熟悉,它告诉我们要使用 pipeline 对象,指定对话任务,并通过在此处填入模型名称来加载模型。

处理多轮对话 💭

现在,让我们尝试进行多轮对话。例如,接着问聊天机器人:“你还有其他推荐吗?”

如果我们简单地创建一个包含新问题的新对话对象,助手给出的答案将与之前的冬季活动对话无关,因为它不记得早先的对话。

正确的方法是向现有的对话对象中添加新消息。大语言模型本身不会自然记住你之前的消息,但当你使用 Conversation 对象时,你可以添加后续消息。该对象会保存你之前的提示以及 LLM 的回复,从而使 LLM 能够像记得早先对话一样与你交流。

让我们试一下:

conversation.add_user_input(“What else do you recommend?”)
conversation = chatbot(conversation)
print(conversation.generated_responses[-1])

如你所见,助手的回答显示出对之前关于冬季活动的对话有一定的记忆。由于模型非常小,回答可能不够深入。如果你有足够的硬件来运行它们,有许多先进的开源模型可以表现得相当出色。

了解开源模型生态 🌐

在 Hugging Face,我们有一个开放大语言模型排行榜,使用户和公司能够评估开源 LLM 和聊天机器人。让我们看看哪些聊天机器人表现最好。我们首先只选择预训练模型(即从头开始训练的模型)。

排行榜顶部的模型大多来自大公司,因为并非每个人都有能力训练这些大型模型。你可以看到一些熟悉的名字,例如新的 Mixtral 模型、Falcon 模型、Yi 模型和 Qwen 模型。

围绕这个排行榜存在很多讨论,人们怀疑所选的基准测试是否能代表模型的真实性能。我们知道它们并不完美,但我们会不断增加更多基准测试,以便能够公平地评估所有模型。

如果你想查看另一个排行榜,可以看看 Chatbot Arena 排行榜。该排行榜收集了超过 20 万次人类偏好投票,使用 Elo 排名系统对 LLM 进行排序。排行榜中包含 GPT-4 等专有模型,但正如你在列表中看到的,开源模型也正在快速追赶专有模型。

例如,列表中的 Mixtral 模型采用 Apache 2.0 许可证,这意味着它允许你使用、修改和分发该模型,也可以将其用于商业用途。


总结 📝

本节课中,我们一起学习了自然语言处理的基础概念,并使用 Hugging Face Transformers 库的 pipeline 函数,基于 Meta 的 Blenderbot 模型构建了一个简单的聊天机器人。我们探讨了如何为特定任务(如对话)在 Hugging Face Hub 上选择合适的模型,并学习了如何使用 Conversation 对象来处理多轮对话,使模型能够保持一定的对话上下文。最后,我们简要了解了当前开源大语言模型的生态和评估方式。

在下一节课中,我们将学习如何总结长文档以及将文本从英语翻译成法语。

004:翻译与摘要 📚

在本节课中,我们将学习如何使用Hugging Face的开源模型完成两项核心任务:文本翻译文档摘要。我们将使用Meta公司发布的模型,将英文文本翻译成法文,并对长文档进行内容总结。

环境准备与库导入 🛠️

开始之前,需要确保必要的库已安装。在本课程环境中,这些库已预先安装好。如果您在自己的机器上运行,需要手动安装。

以下是需要安装的库:

  • Transformers库pip install transformers
  • PyTorch库pip install torch

由于课程环境已就绪,我们直接导入所需的函数。

# 导入pipeline函数和torch
from transformers import pipeline
import torch

文本翻译 🌐

上一节我们导入了核心工具,本节中我们来看看如何构建一个翻译器。

首先,我们使用 pipeline 函数创建一个翻译管道。需要指定任务类型、模型,并为了高效运行,设置模型的数据类型。

# 创建翻译管道
translator = pipeline(
    task="translation", # 指定任务为翻译
    model="facebook/nllb-200-distilled-600M", # 使用Meta的NLLB模型
    torch_dtype=torch.bfloat16 # 使用bfloat16数据类型压缩模型,保持性能
)

这里使用的模型是Meta的 NLLB(No Language Left Behind),它支持200种不同语言之间的翻译。设置 torch_dtype=torch.bfloat16 可以在几乎不损失精度的情况下减少模型内存占用。

现在翻译器已加载,可以开始翻译文本了。

以下是翻译的步骤:

  1. 准备要翻译的英文文本。
  2. 调用翻译器,指定源语言和目标语言。
# 定义要翻译的文本
text_to_translate = "Hello, my name is LLaMA. I'm a helpful AI assistant created by Meta AI."

# 执行翻译
translated_text = translator(text_to_translate, src_lang="eng_Latn", tgt_lang="fra_Latn")

# 查看翻译结果
print(translated_text[0]['translation_text'])

代码中,src_lang="eng_Latn" 表示源语言是英文,tgt_lang="fra_Latn" 表示目标语言是法文。每种语言都有特定的代码,可以在相关文档中查找。

执行后,文本被成功翻译成法文。您可能会注意到某些翻译细节(如专有名词“LLaMA”)可能不够完美,这展示了当前模型的能力与局限。

建议您在此暂停视频,尝试翻译自己的文本或更换其他目标语言进行实验。

完成翻译任务后,为了释放内存以进行下一项任务,我们清理当前模型。

import gc

# 删除翻译器以释放内存
del translator
gc.collect() # 调用垃圾回收

文档摘要 📄

我们已经学会了翻译,接下来看看如何用管道轻松实现文档摘要。

创建摘要管道与翻译类似,只需更改任务和模型。

# 创建摘要管道
summarizer = pipeline(
    task="summarization", # 指定任务为摘要
    model="facebook/bart-large-cnn", # 使用Meta的BART-large-CNN模型
    torch_dtype=torch.bfloat16 # 同样使用bfloat16压缩模型
)

这里我们使用了Meta的 BART-large-CNN 模型,它特别擅长生成文本摘要。

现在,让我们对一段关于巴黎的长文本进行总结。

# 定义长文本
long_text = """
Paris is the capital and most populous city of France. It is located on the Seine River in the north of the country. Known as the ‘City of Light’, Paris is famous for its art, culture, and history. Major landmarks include the Eiffel Tower, the Louvre Museum (home to the Mona Lisa), and the Notre-Dame Cathedral. The city is also a global center for fashion, gastronomy, and luxury goods. Paris hosts numerous international organizations such as UNESCO. With its charming streets, cafes, and vibrant cultural life, it remains one of the world's top tourist destinations.
"""

![](https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-hf-osmdl/img/bf51082d585dfed0df66acc4f7301ae0_6.png)

# 执行摘要生成
summary = summarizer(long_text, max_length=100, min_length=10)[0]['summary_text']

# 查看摘要结果
print(summary)

在调用摘要器时,我们通过 max_lengthmin_length 参数控制了摘要的长度范围,使输出更加精炼。

模型生成了一段简洁的摘要,概括了原文关于巴黎的核心信息。

鼓励您在此暂停,尝试从网上找一些文章或长邮件,用这个管道进行摘要实践。

课程总结 🎯

本节课中我们一起学习了如何使用Hugging Face的pipeline接口快速实现两大实用NLP任务:

  1. 文本翻译:利用Meta的NLLB模型,在多种语言间进行翻译,并了解了如何指定语言代码和控制模型精度。
  2. 文档摘要:利用Meta的BART-large-CNN模型,将长文档浓缩为简洁的摘要,并掌握了控制摘要长度的方法。

这些任务展示了开源预训练模型的强大能力,只需几行代码即可投入应用。在下一节课中,我们将探索如何测量两个句子之间的相似度,这是一个在信息检索、问答系统中非常有用的任务。

Hugging Face开源模型课程:P5:句子嵌入与相似度计算

在本节课中,我们将学习如何使用 sentence-transformers 库来测量句子之间的相似度。句子相似度衡量的是两段文本在语义上的接近程度。这在信息检索、文本聚类或分组等任务中非常有用。


加载库与模型

首先,我们需要加载必要的库和模型。在本课程环境中,相关库已预先安装。如果你在自己的机器上运行,可以通过 pip install sentence-transformers 命令进行安装。

我们从 sentence-transformers 库中导入 SentenceTransformer 类。这个类允许你加载多种预训练模型。

# 导入SentenceTransformer类
from sentence_transformers import SentenceTransformer

要加载一个特定的模型,只需将模型名称传递给 SentenceTransformer 类。本节课我们将使用 all-MiniLM-L6-v2 模型来计算句子相似度。这个模型是2021年Hugging Face与谷歌组织的“社区周”活动中,由开源社区训练出来的成果之一。

# 加载预训练模型
model = SentenceTransformer('all-MiniLM-L6-v2')

将句子编码为向量(嵌入)

句子相似度模型的核心功能是将输入的文本转换为向量,也称为“嵌入”。这些嵌入向量能够捕捉文本的语义信息。

让我们来编码第一组句子:

# 定义第一组句子
sentences1 = [
    "The cats sit outside",
    "A man is playing guitar",
    "The movies are awesome"
]

# 将句子编码为向量,并确保输出为张量格式
embeddings1 = model.encode(sentences1, convert_to_tensor=True)

# 打印嵌入向量
print("第一组句子的嵌入向量:")
print(embeddings1)

如你所见,我们成功地将文本转换成了数值向量。

现在,我们对第二组句子进行同样的操作:

# 定义第二组句子
sentences2 = [
    "The dog plays in the garden",
    "A woman watches TV",
    "The new movie is so great"
]

# 编码第二组句子
embeddings2 = model.encode(sentences2, convert_to_tensor=True)

print("\n第二组句子的嵌入向量:")
print(embeddings2)

计算句子相似度

上一节我们成功将句子转换成了向量。本节中,我们来看看如何计算这些向量之间的相似度。我们将使用余弦相似度作为衡量标准,它计算的是两个向量在方向上的接近程度。

首先,我们需要从 sentence-transformers 库中导入用于计算相似度的工具函数。

# 导入相似度计算工具
from sentence_transformers import util

计算相似度非常简单,只需调用 util.cos_sim 函数并传入两组嵌入向量即可。

# 计算两组句子嵌入之间的余弦相似度
cosine_scores = util.cos_sim(embeddings1, embeddings2)

print("句子相似度矩阵:")
print(cosine_scores)

输出的矩阵显示了第一组中每个句子与第二组中每个句子的相似度得分。矩阵对角线上的元素,分别对应着两组列表中位置相同的句子之间的相似度。

为了更清晰地查看配对结果,我们可以按对输出得分:

# 遍历所有句子对,打印相似度得分
for i in range(len(sentences1)):
    for j in range(len(sentences2)):
        print(f"句子1: \"{sentences1[i]}\"")
        print(f"句子2: \"{sentences2[j]}\"")
        print(f"相似度得分: {cosine_scores[i][j]:.2f}\n")

结果分析

以下是配对分析的结果:

  • “The cats sit outside” 与 “The dog plays in the garden”:得分约为 0.28。这表明两个句子存在一定的相似性,模型可能捕捉到了“猫”和“狗”都是宠物以及“外面”和“花园”都是户外场所的语义关联。
  • “A man is playing guitar” 与 “A woman watches TV”:得分非常低(接近0)。这符合预期,因为这两个句子描述的是完全不同的活动,几乎没有语义重叠。
  • “The movies are awesome” 与 “The new movie is so great”:得分约为 0.65。这是正确的,因为这两个句子都表达了对电影的积极评价,含义高度相似。

总结

本节课中,我们一起学习了如何使用 sentence-transformers 库进行句子相似度计算。我们首先加载了一个预训练的句子嵌入模型,然后将文本句子编码为语义向量,最后通过计算余弦相似度来量化句子之间的语义接近程度。你可以尝试使用这个工具完成其他任务,例如文本分类、零样本分类或问答。让我们继续下一节课的学习。

006:零样本音频分类 🎵

在本节课中,我们将学习如何构建一个无需微调的音频分类器。我们将使用Hugging Face的CLAP模型,通过比较音频与文本标签的相似度,来识别声音的类别。这种方法特别适用于没有针对特定类别进行过训练的模型场景。

音频分类有许多应用场景。例如,你可能想识别某人正在说的语言,或者想知道你所在区域有哪些鸟类。

音频分类的传统挑战

让我们构建一个声音分类器,但传统分类方法存在一个限制。在传统分类中,模型从一个预定义的、它训练过的类别集合中预测标签。如果没有针对你特定类别集合训练过的模型,你就必须收集数据集并微调一个模型。

在这里,你将使用一种不需要微调的替代方法。

准备环境与数据

对于这个课堂环境,所需的库已经为你安装好了。如果你在自己的机器上运行,可以通过运行以下命令来安装 transformersdatasets 和其他必需的库。我将把它们注释掉,因为它们在这里已经安装了。

我们需要一个声音来进行分类。所以,让我们从Hugging Face Hub加载一个音频数据集。ESC50数据集是一个包含5秒环境声音的带标签集合,例如动物和人类发出的声音、自然声音、室内声音、城市噪音等。你不需要整个数据集,所以我们只加载几个示例。

这个示例被标记为“狗”。所以它很可能是一段狗叫的录音,让我们听一下。

听起来像狗叫声。接下来,让我们构建分类流程。

构建分类流程

对于这种音频分类,你将需要一个预训练的CLAP模型。目前,它是可用于此任务的唯一一种架构,因此你可以在Hugging Face Hub上通过筛选特征提取、多模态任务,然后按名称“clap”来找到它。

为了对你的音频示例进行分类,你只需要音频数据的数组。然而,示例必须具有模型期望的采样率。让我们退一步谈谈采样率。

理解采样率

声波是一个连续信号。这意味着在给定时间内它包含无限数量的信号值,但你的计算机可以处理的音频是一系列离散值,称为数字表示。

为了获得连续音频信号的数字表示,我们首先用麦克风捕获声音。然后模拟信号被转换为电信号。接着,电信号被采样以获得数字表示。

采样意味着在固定的时间步长测量连续信号的值。结果,采样后的波形是离散的,在均匀间隔处具有有限数量的值。

数字化音频的一个非常重要的特性是采样率。它是一秒钟内采集的样本数,以赫兹或千赫兹为单位测量。例如,8千赫兹是电话或对讲机中音频的采样率;16千赫兹是足以清晰捕捉人类语音而不显得沉闷的采样率;192千赫兹的采样率是你可以从专业高保真音频录制设备中预期的。

采样率对AI模型的重要性

但为什么采样率在处理AI模型时很重要?考虑一个例子:一个5秒的声音,采样率为8千赫兹,将被表示为40,000个信号值的序列。相同的5秒声音样本在16千赫兹下将表示为80,000个信号值的序列,而在192千赫兹下,它将用近一百万个值表示。

对于Transformer模型,这三个数组非常不同。Transformer模型将输入视为序列,并依赖注意力机制来学习音频表示。它们在所有示例都具有相同采样率的数据集上进行训练,并且不能很好地泛化到其他采样率。因此,对于一个在16千赫兹音频上训练的Transformer模型,一个用近百万个值表示的高质量5秒音频,看起来会像一段60秒的录音。

回到代码:处理采样率

让我们回到代码。如果一个Transformer模型是用每个都以48千赫兹采样率录制的音频样本训练的,那么它将把任何输入都视为以相同采样率录制的。所以,让我们拿一个以192千赫兹采样率录制的1秒声音。代表该声音的数组将有多少个值?

192,000个值。但如果我们采用一个在16千赫兹采样率的音频示例上训练的模型,它会将其视为1秒还是更长?让我们看看。模型将看到192,000个值。它期望1秒包含16,000个值。所以对于这个模型,录音看起来像是12秒。

那么,如果我们现在有一个5秒的高清录音(即192千赫兹),而模型是在16千赫兹的音频样本上训练的,这个5秒的高清录音对这个模型来说看起来有多长?我们有5秒乘以每秒192,000个值。所以这个样本将是一个960,000个值的数组。模型期望每秒包含16,000个值。让我们将我们拥有的值数量除以16,000。这样,我们就能看到模型会认为这个示例是多少秒。

如你所见,原始声音只有5秒,但每秒有很多样本。然而,对于一个以较低采样率训练的模型,这个确切的音频看起来像一段60秒的录音。

调整数据采样率

现在让我们回到我们的任务,检查本课中模型期望的采样率。我们可以从流程中获取此信息。所以这个模型是在以48千赫兹录制的音频示例上训练的。让我们检查我们示例的采样率。

在这种情况下,采样率的差异不大,模型可能表现尚可。但情况并非总是如此,正如你在其他示例中将看到的那样。所以,让我们看看在使用datasets库加载数据集时,如何自动将整个数据集转换为正确的采样率。

让我们再次检查第一个采样。现在它具有与模型相同的采样率。当你以这种方式加载数据集时,所有音频示例都将具有正确的采样率。

使用CLAP模型进行分类

现在音频样本已准备好供模型使用。然而,你还需要为流程提供候选标签。CLAP同时接受音频和文本作为输入,并计算两者之间的相似度。如果你传递与音频输入强相关的文本输入,你将获得高相似度分数。相反,传递与音频输入完全无关的文本输入将返回低相似度分数。

所以,让我们定义一些候选标签来与样本进行比较。

将音频样本和候选标签传递给流程,看看哪个标签最有可能。

现在尝试两个以上的候选标签,然后尝试一些完全无关的标签。看看你是否能对这种方法的局限性有一些直观理解。

让我们尝试一些完全无关的标签。我们将使用相同的流程和相同的音频样本。记住,那是一段狗叫声。

如你所见,候选标签现在与狗或叫声无关。然而,模型仍然试图在给定的选项中找出最合理的标签。

总结与下节预告

在本节课中,我们一起学习了零样本音频分类。我们了解了采样率的重要性,以及如何将音频数据调整到模型期望的采样率。我们使用了Hugging Face的CLAP模型,通过比较音频与一系列文本标签的相似度来对声音进行分类,而无需对模型进行任何微调。这种方法为快速原型设计和探索性任务提供了便利。

在下一课中,我们将进行自动语音识别。

007:使用Hugging Face进行语音转文字 📝

在本节课中,我们将学习自动语音识别任务。你将了解如何使用Hugging Face库和OpenAI的Whisper模型,将语音录音转录为文本。我们还将构建一个简单的转录演示应用。

自动语音识别是一项将语音录音转录为文本的任务。例如,会议记录或自动生成视频字幕。对于此任务,你将学习使用OpenAI的Whisper模型。

加载语音数据集 🗣️

与之前一样,所有必要的库都已为你安装好。但如果你在自己的机器上运行,则需要与之前相同的库集,外加音频接口。这次我们加载LibriSpeech数据集。这是一个包含约1000小时数据的语料库,数据来源于有声读物朗读。

音频数据集通常非常大,因此了解如何以流模式加载它们很有用。这样,示例将根据需要逐个加载。对于流式数据集,你可以逐个访问示例,这是获取第一个示例的方法。

顺便说一下,如果你想访问多个示例,例如前五个,可以使用take函数。在此列表中,你可以使用索引访问各个示例。你可以选择你喜欢的任何示例,但现在我们坚持使用第一个。与之前一样,你只需要此示例的音频部分。让我们听一下这段叙述。

选择与加载模型 🤖

Hugging Face Hub上有数千个用于自动语音识别的预训练模型。你可以通过选择自动语音识别任务来找到它们。然而,OpenAI的Whisper仍然是此任务的最佳模型之一。Whisper在大量带标签的音频转录数据上进行了预训练,准确地说,是68万小时。更重要的是,其中11.7万小时的预训练数据是多语言或非英语的。这产生了可应用于超过96种语言的检查点。这里为了效率,我们将使用模型的蒸馏版本,该版本仅适用于英语。所谓蒸馏,是指使用完整Whisper模型的响应进行训练的较小模型。此检查点比大模型小10倍以上,快5倍,且单词错误率在大模型的3%以内。

与之前一样,让我们检查Whisper期望的采样率。

现在,让我们看看示例的采样率是多少。这次它们相同,所以我们可以将音频原样传递给流水线。它成功了。现在让我们将其与示例附带的转录进行比较。

请注意,与示例附带的转录不同,Whisper返回的转录带有正确的大小写和标点符号,这使得它更容易阅读。

构建转录演示应用 🎤

现在,让我们构建一个简单的转录演示,我们将为此使用Gradio。让我们创建一个transcribe_speech函数,它将作为我们流水线的包装器。

接下来,你可以创建一个选项卡式界面,其中一个选项卡允许从麦克风录制音频,另一个选项卡允许用户上传音频文件。

以下是我们创建允许用户从麦克风录制音频的选项卡的方法:我们需要创建一个Gradio界面,传递transcribe_speech函数,定义音频输入来源(本例中为麦克风),以及输出应呈现的形式(本例中为文本框)。

如果你想了解更多关于Gradio的信息,有一门关于部署AI的课程。

我们将以同样的方式创建用于上传文件的选项卡。

现在,只需将所有内容整合在一起并启动演示。尝试演示,尝试录制自己对着麦克风说话,或尝试上传音频文件,看看转录是否与你所说的内容匹配。

让我们测试Whisper是否能转录我现在说的话。

尝试说大约一分钟,看看转录会发生什么。你可能会注意到,如果你说话时间超过30秒,此演示只转录了你所说的部分内容。这是因为Whisper期望音频样本在30秒以下,其他所有内容都将被截断。实际上,你可能希望转录更长的录音,例如整个会议。你仍然可以使用此流水线完成此操作,但需要提供一些额外的参数。

处理长音频文件 ⏱️

让我们直接说明这一点。首先,我们获取一个更长的音频示例。我们将停止演示,否则它将阻止我们运行更多单元格。要停止Gradio演示,请单击中断内核的方形图标。

我们将使用相同的自动语音识别流水线。让我们再次检查模型期望的采样率。

现在,采样率存在很大差异。

错误信息显示模型期望单声道音频输入,而我们可能有不止一个声道。

我们可能正在处理立体声音频。立体声使用双声道音频。这有助于在声音中创造空间感和方向感,从而增强聆听体验。立体声擅长为音频添加空间分量。因此,当你听音乐时,你会获得更好的体验,但对于Transformer模型来说,通常不需要。大多数Transformer模型使用单声道音频。这是因为你实际上不需要空间信息来识别声音是狗叫还是猫叫,你不需要知道语音来自哪里,你只需要知道说了什么。同时,立体声音频有两个声道,所以数据量是两倍,这增加了计算的复杂性,而没有真正提供任何好处。

让我们看看如何将此音频转换为单声道。让我们检查音频数组的形状。

如你所见,此音频中有两个声道,但我们只需要一个。我们将使用一个名为Librosa的库将此音频数组从立体声转换为单声道。Librosa期望音频数组的形状是声道数在前,然后是数据,所以在进行转换之前,还需要一步,即转置此数组。

让我们再次检查形状。现在,让我们将此音频转换为单声道。完成后,让我们听一下这个示例。

好的,让我们尝试直接将此音频传递给流水线,看看会发生什么。

哦,不,模型生成的文本与音频并不真正匹配。为什么会这样?这是因为音频示例的采样率与模型的采样率不匹配。模型试图猜测生成的内容,但未能成功。让我们仔细检查一下。让我们看看这个示例的采样率是多少。

示例的采样率是44.1千赫兹。让我们看看流水线期望什么。

流水线期望音频以16千赫兹采样。让我们修复这个问题。我们可以使用Librosa重新采样单个文件。

现在,音频示例已准备好用于流水线。为了使流水线能够转录更长的视频,我们需要向它传递一些参数。但首先,让我们谈谈自动语音识别流水线如何处理更长的录音。因为Whisper一次只能处理最多30秒的音频。为了转录这个更长的示例,流水线会将长文件分割成块。我们可以为Whisper指定块长度,30秒的块是最佳的,因为这匹配模型期望的输入。每个段将与前一个段有少量重叠。这使得流水线能够在边界处准确地将段拼接在一起,因为它可以找到段之间的重叠并相应地合并转录。由于音频被分割成块,流水线可以独立转录每个块,然后合并结果。因此,你可以并行转录一批块。

让我们看看将传递给流水线的参数。

接下来是块的长度,本例中为30秒。

接下来,我们将指定希望并行处理多少个块,使用batch_size。在本例中,原始文件只有1分21秒,因此不需要将batch_size设置为大于三或四。对于更大的文件,batch_size将取决于你的硬件和可用内存。如果你尝试较大的batch_size并出现内存不足错误,你就知道需要尝试较小的批处理大小。在第一节介绍课中,我给了你一个经验法则来估算运行模型所需的内存量。要估算batch_size,可以将其视为该内存量的乘数,即你可以并行运行多少个模型。因此,如果你有硬件支持,可以拥有大量的批处理。在本例中,对于管理器来说,我们也不需要更多,因为30秒的分割带有一点重叠可能甚至是冗余的,也许我们可以做三个。但以防万一,对于这种情况,三或四个是可以的。尝试并实验批处理大小,看看你的硬件能处理什么。

最后,你可以将return_timestamps设置为True,这可以预测音频数据的段级时间戳。这些时间戳指示短段音频的开始和结束时间,对于将转录与输入音频对齐特别有用。要输出带时间戳的转录,你可以打印输出的chunks部分。

现在我们获得了完整音频的转录,并且得到了时间戳。

修改演示以接受长音频录音 🔧

现在,让我们看看如何修改演示以接受更长的音频录音。首先,让我们复制原始演示。让我们复制transcribe_speech函数。

在这里,我们将修改调用流水线的方式。我们不只是给它音频文件,还将传递额外的参数。

我们需要在界面中更新的唯一内容是函数的名称。

启动演示的代码片段没有变化。所以它已经准备好了。

尝试上传一个超过30秒的音频文件,或者再次录制自己对着麦克风说话超过30秒,看看它是否有效。

在本节课中,我们一起学习了自动语音识别的基础知识,包括加载数据集、使用Whisper模型进行转录、处理立体声和采样率问题,以及构建和扩展一个能够处理长音频的转录演示应用。在下一课中,你将学习如何朝相反方向进行,即从文本到语音。

008:文本转语音(TTS)

在本节课程中,我们将学习如何将文本转换为语音,即文本转语音(Text-to-Speech, TTS)任务。这是音频生成领域的最后一个环节,我们将使用Hugging Face上的一个开源模型来实现这一功能。

概述:文本转语音的挑战

文本转语音是一项具有挑战性的任务,因为它是一个“一对多”问题。在分类任务中,一个输入通常对应一个或几个正确的标签。在自动语音识别中,一段语音通常对应一个正确的文本转录。然而,对于同一句话,存在无数种不同的朗读方式。每个人的声音、方言、说话风格都不同,但所有这些方式都是有效且正确的。

尽管存在这些挑战,开源社区已经开发出能够出色处理此任务的模型。接下来,我们将使用其中一个模型。

使用VITS预训练模型

我们将使用来自Cacao Enterprise的VITS预训练模型。这是少数几个能在此学习环境中运行的模型之一,并且它拥有宽松的开源许可协议。

一旦我们建立了处理管道(pipeline),只需要向其中传入文本即可。

以下是创建和使用TTS管道的步骤:

  1. 导入并加载管道
    首先,我们需要从transformers库中导入pipeline函数,并指定我们要使用的模型。

    from transformers import pipeline
    
    # 创建文本转语音管道,指定模型
    tts_pipeline = pipeline("text-to-speech", model="facebook/mms-tts-eng")
    
  2. 准备输入文本
    接下来,我们准备一段希望转换为语音的文本。

    # 定义要转换的文本
    text_to_speak = "Researchers at the Allen Institute, AI, Microsoft, the University of Washington, Carnegie Mellon University and the Hebrew University of Jerusalem developed a tool that measures atmospheric carbon emitted by cloud servers while training machine learning models. The biggest variables were the server's location and time of data use."
    
  3. 生成并播放音频
    最后,我们将文本传入管道,生成音频数据,并可以将其保存为文件或直接播放。

    # 生成语音
    speech_output = tts_pipeline(text_to_speak)
    
    # 将音频数据保存为WAV文件
    import soundfile as sf
    sf.write("output_speech.wav", speech_output["audio"], samplerate=speech_output["sampling_rate"])
    
    # 或者在Jupyter Notebook等环境中直接播放
    # from IPython.display import Audio
    # Audio(speech_output["audio"], rate=speech_output["sampling_rate"])
    

运行上述代码后,你将得到一个名为output_speech.wav的音频文件,其中包含了模型根据输入文本生成的语音。你可以自由替换text_to_speak变量中的内容,尝试生成不同的语音。

总结

在本节课中,我们一起学习了文本转语音的基本概念。我们了解到TTS是一个“一对多”的生成任务,并实践了如何使用Hugging Face的transformers库和VITS预训练模型,通过简单的几步将任意文本转换为语音。只需加载管道、传入文本,即可获得合成的音频输出。

在下一节课中,Eunice将向你展示如何构建一个目标检测器。让我们继续学习。

009:目标检测 🎯

在本节课中,我们将探索计算机视觉模型,并动手实践,构建一个能够帮助视障人士理解图片内容的智能助手。我们将重点学习目标检测任务,并使用Hugging Face的transformers库来实现它。

概述

目标检测是计算机视觉中的一项核心任务,它不仅能识别图像中的物体,还能定位它们的位置。本节课我们将学习如何使用Hugging Face Hub上的预训练模型进行目标检测,并将检测结果转化为语音描述,从而构建一个完整的AI助手。


环境准备与模型加载

在开始之前,请确保已安装必要的库。如果你在自己的机器上运行,可以使用以下命令安装:

pip install transformers torch pillow gradio

首先,我们需要导入一些工具函数和pipeline

from transformers import pipeline
# 假设 helper 模块中定义了 load_image_from_url 和 render_results_on_image 函数
from helper import load_image_from_url, render_results_on_image

接下来,我们加载目标检测模型。我们将使用Facebook的Detr-ResNet-50模型。

od_pipe = pipeline("object-detection", model="facebook/detr-resnet-50")

理解目标检测任务

上一节我们加载了模型,本节我们来深入了解一下目标检测任务。

目标检测的任务是识别图像中感兴趣的物体,并为每个检测到的物体提供类别标签边界框位置。它结合了分类和定位两个子任务。

公式表示:对于一个图像 I,目标检测模型 f 的输出是一组边界框 B 和对应的类别标签 C 及置信度 S
f(I) = {(B_i, C_i, S_i)} for i = 1 to N

如何选择模型?你可以访问Hugging Face Hub,使用左侧的“Object Detection”过滤器浏览所有可用模型。选择模型时,可以参考下载量、点赞数以及模型卡中提供的在特定数据集上的评估指标。


使用模型进行预测

现在,让我们使用加载好的管道对一张图片进行预测。以下是操作步骤:

  1. 加载一张图片。
  2. 将图片传入管道。
  3. 使用辅助函数可视化结果。

# 加载示例图片(这里假设通过 helper 函数从URL加载)
image = load_image_from_url("https://example.com/your_image.jpg")

# 进行预测
predictions = od_pipe(image)

# 在图片上渲染结果
result_image = render_results_on_image(image, predictions)
result_image.show()

运行后,你将看到原图上绘制了边界框,并标注了物体类别和置信度。模型成功检测出了人、瓶子、杯子等物体。

你可以暂停视频,尝试使用自己的本地图片或网络图片URL进行测试。


创建交互式演示应用

为了让模型更易于使用和分享,我们可以使用Gradio库创建一个简单的Web界面。

以下是创建界面的步骤:

  1. 定义一个处理函数,它接收图片并返回带标注的结果图片。
  2. 使用GradioInterface类包装这个函数。
  3. 启动应用。

import gradio as gr

def get_pipeline_prediction(pil_image):
    # 使用全局已加载的管道进行预测
    predictions = od_pipe(pil_image)
    # 渲染结果
    result_image = render_results_on_image(pil_image, predictions)
    return result_image

# 创建Gradio界面
demo = gr.Interface(
    fn=get_pipeline_prediction,
    inputs=gr.Image(type="pil"),
    outputs=gr.Image(type="pil"),
    title="目标检测演示"
)

![](https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-hf-osmdl/img/904b131b94f40a51c0dfe9cff001e295_27.png)

# 启动应用,并生成可分享的链接
demo.launch(share=True)

运行这段代码后,会弹出一个本地网页。你可以上传图片,点击“Submit”,右侧就会显示检测结果。通过share=True参数生成的链接,你可以与朋友分享这个应用。


构建AI视觉助手

最后,我们将结合目标检测和文本转语音模型,构建一个能“描述”图片的AI助手。

整个流程分为三步:

  1. 目标检测:识别图片中的物体及其数量。
  2. 文本生成:将检测结果组织成一句自然的描述文本。
  3. 语音合成:将描述文本转换为语音。

首先,我们处理目标检测的输出,将其总结成一句话。假设我们有一个辅助函数summarize_predictions_natural_language来完成这个任务。

from helper import summarize_predictions_natural_language

# 对同一张图片进行预测
predictions = od_pipe(image)
# 生成描述文本
description_text = summarize_predictions_natural_language(predictions)
print(description_text)
# 输出示例:“在这张图片中,有2把叉子,3个瓶子,2个杯子,4个人,1个碗和1张餐桌。”

接着,我们使用文本转语音模型将这段描述读出来。

# 加载文本转语音管道
tts_pipe = pipeline("text-to-speech", model="kakao-enterprise/vits-ljs")

# 生成语音
speech_output = tts_pipe(description_text)

# 播放语音(需要IPython环境或保存为文件)
# 例如,保存为文件
import scipy.io.wavfile as wavfile
wavfile.write("output_audio.wav", rate=speech_output["sampling_rate"], data=speech_output["audio"])

现在,你可以听到AI助手用语音描述图片内容了。你可以将整个流程封装成一个函数或另一个Gradio应用,方便他人使用。


总结

在本节课中,我们一起学习了:

  1. 目标检测的概念与原理,它结合了分类与定位。
  2. 如何使用Hugging Face的pipeline快速加载和使用预训练的目标检测模型。
  3. 如何利用Gradio库为模型构建一个用户友好的交互式Web演示界面。
  4. 如何将目标检测模型与文本转语音模型结合,创建一个能够描述图片内容的AI视觉助手。

你可以尝试使用Hub上的其他模型,比较它们的性能,并将整个流程打包成应用与朋友分享。

010:图像分割与深度估计 🖼️

在本节课中,我们将学习两种计算机视觉任务:图像分割和深度估计。我们将使用Hugging Face的transformers库,探索Segment Anything Model(SAM)和Dense Prediction Transformer(DPT)模型。通过实践,你将学会如何通过视觉提示(如指定一个点)来分割图像中的特定对象,以及如何估计图像的深度信息。


图像分割与掩码生成 🎯

上一节我们介绍了课程概述,本节中我们来看看图像分割,特别是掩码生成任务。

传统的图像分割任务会为图像中的每个像素预测一个类别标签。例如,天空的像素被标记为“天空”,桥梁的像素被标记为“桥梁”。

公式像素标签 = 模型(输入图像)

而掩码生成任务则不同。它允许用户通过视觉提示来引导模型,例如在图像上指定一个点或一个边界框,模型将预测该感兴趣对象的精确分割掩码。Segment Anything Model(SAM)就是这样一个模型。与经典分割不同,预测出的掩码没有类别标签,它只表示“这是用户指定的那个对象”。

此外,SAM还支持自动掩码生成。该流程会在图像上采样多个点,尝试不同的点组合,并筛选出得分最高的分割掩码,从而得到图像中所有主要对象的掩码。

为了在硬件资源有限的环境下运行,本实验将使用SAM的一个轻量级、压缩版本——SSM模型,它在保持相似性能的同时,模型体积更小。


使用Pipeline进行自动掩码生成 🤖

理解了基本概念后,我们开始动手实践。首先,我们将使用pipeline对象进行自动掩码生成。

以下是初始化掩码生成pipeline的步骤:

  1. transformers库导入pipeline
  2. 指定任务为mask-generation,并加载SSM模型。
from transformers import pipeline

pipe = pipeline("mask-generation", model="facebook/sam-vit-base")

接下来,我们加载一张示例图片。图片中包含人物和羊驼。

对于自动掩码生成,可以设置points_per_batch参数。更高的值意味着推理更高效,但对硬件要求也更高。对于小型硬件,建议使用较小的值。

运行pipeline后,我们使用一个辅助函数来可视化结果。可以看到,模型成功分割了图像中的许多小区域,例如每个人的头部、每只羊驼、墙壁和背景中的小物件。

这种方法的缺点是需要在所有采样点上迭代并后处理生成的掩码,对于某些应用场景可能较慢。


使用视觉提示进行精确分割 ✨

上一节我们使用pipeline进行了全图分割,本节中我们来看看如何通过指定点来进行精确分割。

我们将直接使用模型类和处理器,而不是pipeline。首先加载模型和处理器:

from transformers import SamModel, SamProcessor
import torch

model = SamModel.from_pretrained("facebook/sam-vit-base")
processor = SamProcessor.from_pretrained("facebook/sam-vit-base")

我们使用同一张图片,并希望分割图中Andrew的蓝色衬衫。为此,我们在衬衫区域指定一个二维坐标点(例如[1600, 700],坐标系原点在左上角)。

以下是编码和推理步骤:

  1. 使用处理器同时编码图像和输入点。
  2. torch.no_grad()上下文管理器中进行推理,以避免计算梯度。
# 准备输入
input_points = [[[1600, 700]]] # 格式:[[[x, y]]]
inputs = processor(image, input_points=input_points, return_tensors="pt")

# 推理
with torch.no_grad():
    outputs = model(**inputs)

模型会一次性预测三个分割掩码及其置信度分数。我们需要后处理这些掩码,将它们调整到原始图像尺寸,并选择置信度最高的一个。

# 后处理掩码
masks = processor.post_process_masks(outputs.pred_masks, inputs["original_sizes"], inputs["reshaped_input_sizes"])
best_mask = masks[0][0][0] # 取第一个图像的第一个掩码

可视化结果显示,三个预测掩码中有两个准确地分割出了衬衫区域,另一个则分割出了整个人物。为了获得更好的效果,可以尝试为同一个掩码提供多个点,或者提供一个包围目标区域的边界框。


使用DPT模型进行深度估计 📏

现在我们已经学会了如何使用SAM分割对象,接下来看看另一个任务:深度估计。我们将使用DPT(Dense Prediction Transformer)模型。

深度估计是计算机视觉中的常见任务,例如在自动驾驶中广泛应用。我们将使用Intel的dpt-hybrid-midas模型。

同样,我们使用pipeline来简化流程:

from transformers import pipeline

depth_estimator = pipeline("depth-estimation", model="Intel/dpt-hybrid-midas")

加载一张测试图片(例如一个站在路上的玩具),然后进行深度估计:

output = depth_estimator(image)
predicted_depth = output["predicted_depth"] # 原始的深度张量

模型输出的深度图尺寸可能与原图不同。我们需要将其调整到原图尺寸,并将值归一化到0-255范围以便显示。

import torch.nn.functional as F

# 调整尺寸到原图大小
prediction = F.interpolate(
    predicted_depth.unsqueeze(1),
    size=image.size[::-1], # (高度, 宽度)
    mode="bicubic",
    align_corners=False,
).squeeze()

# 归一化到0-255
formatted = (prediction - prediction.min()) / (prediction.max() - prediction.min()) * 255.0
depth_image = formatted.to(torch.uint8)

可视化深度图,可以看到前景的玩具颜色较亮(深度值小,距离近),背景则颜色较暗(深度值大,距离远),模型预测得相当准确。


创建交互式深度估计演示 🚀

最后,我们可以使用Gradio库将深度估计模型包装成一个交互式Web应用,方便分享。

首先,定义一个处理函数,它接收输入图像,执行所有深度估计和后处理步骤,并返回可视化后的深度图。

import gradio as gr
from PIL import Image
import numpy as np

def depth_estimation_demo(input_image):
    # 1. 使用pipeline估计深度
    output = depth_estimator(input_image)
    predicted_depth = output["predicted_depth"]

    # 2. 调整尺寸和归一化(代码同上,此处省略)
    # ... [调整尺寸和归一化的代码] ...

    # 3. 转换为PIL图像返回
    return Image.fromarray(depth_image.numpy(), mode='L')

然后,创建Gradio界面,指定输入和输出类型为图像,并启动应用。设置share=True可以生成一个可分享的链接。

iface = gr.Interface(
    fn=depth_estimation_demo,
    inputs=gr.Image(type="pil"),
    outputs=gr.Image(type="pil"),
    title="深度估计演示"
)

![](https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-hf-osmdl/img/69c5daf5d98b9c205225587810d4a0e7_25.png)

iface.launch(share=True)

现在,你就可以通过生成的链接与朋友或同事分享这个深度估计工具了。


总结 📝

本节课中我们一起学习了:

  1. 掩码生成与经典图像分割的区别,以及如何使用SAM模型通过视觉提示分割特定对象。
  2. 使用pipeline进行自动掩码生成,以及直接使用模型进行基于点的精确分割
  3. 使用DPT模型进行单图像深度估计,并理解了后处理深度图的关键步骤。
  4. 利用Gradio快速构建和分享一个交互式的深度估计演示应用。

这些技能为你处理更复杂的计算机视觉任务和多模态模型应用打下了基础。

011:图像文本匹配 🖼️🔍

在本节课中,我们将学习使用多模态模型进行图像文本匹配。具体来说,我们将使用Salesforce的开源模型BLIP,来计算一张图片和一段描述文本之间的匹配程度。

什么是多模态模型?🤔

上一节我们介绍了课程目标,本节中我们来看看什么是多模态模型。当一个任务需要模型能够处理多种类型的数据作为输入时,例如同时输入一张图片和一句话,我们称其为多模态模型。本课程中我们将采用这个定义。提到多模态模型,你可能会想到ChatGPT和GPT-4V,它们可以接收文本、图像甚至音频。如果你想尝试开源的多模态聊天模型,也一定要试试Llama。

在接下来的几节课中,我们将学习几个常见的多模态任务:图像文本匹配、图像描述生成、视觉问答以及零样本图像分类。前三个任务我们将使用Salesforce的BLIP模型,最后一个任务(零样本图像分类)我们将使用OpenAI的CLIP模型。

图像文本匹配任务 📊

现在,让我们深入了解第一个任务:图像文本检索或匹配。该模型将判断输入的文本是否与输入的图像匹配。例如,我们传入一张男人和狗的照片,以及文本“穿蓝衬衫的男人戴着眼镜”,模型应该返回文本与图像不匹配。接下来让我们开始编码。

对于本课程,相关库已经安装完毕。如果你在自己的机器上运行,可以通过以下命令安装Transformers库:

# pip install transformers

由于本课程环境已安装所有库,我们无需执行此命令,故将其注释。

加载模型与处理器 🚀

要执行任务,我们需要加载模型和处理器。首先,从Transformers库中导入用于图像文本匹配的BLIP类。

from transformers import BlipForImageTextRetrieval

然后,加载模型。只需调用我们刚导入的类,并使用from_pretrained方法加载预训练的检查点。如前所述,我将使用Salesforce的BLIP模型来执行此任务,这是该特定任务对应的检查点。

model = BlipForImageTextRetrieval.from_pretrained("Salesforce/blip-itm-base-coco")

对于处理器,过程基本相同。我们需要从transformers导入AutoProcessor类。

from transformers import AutoProcessor

接着,加载正确的处理器,同样使用from_pretrained方法并传入相关的检查点。

processor = AutoProcessor.from_pretrained("Salesforce/blip-itm-base-coco")

处理器的角色是为模型处理图像和文本。

准备输入数据 🖼️📝

现在,让我们获取将要传递给处理器的图像和文本。处理器将以模型能够理解的方式修改图像和文本。

对于图像,我们将使用以下URL链接。为了加载图像,我们将使用PIL库的Image类。安装Python时默认会安装PIL库。

from PIL import Image
import requests

url = "你的图片URL"
image = Image.open(requests.get(url, stream=True).raw).convert("RGB")

这段代码从指定URL下载图像,打开它,获取原始二进制数据,然后将其转换为RGB色彩模式。打印image对象,你应该能看到图像。

现在我们有了图像,我们将检查模型是否能成功判断图像与以下文本匹配:“一张女人和狗在海滩上的图片”。

处理输入并运行模型 ⚙️

我们需要获取模型能够理解的输入。为此,我们需要调用处理器,并传入几个参数:图像、文本,并将return_tensors设置为“pt”以获得PyTorch张量。

text = "一张女人和狗在海滩上的图片"
inputs = processor(images=image, text=text, return_tensors="pt")

打印inputs以查看其结构。你会看到一个包含多个参数的字典,例如pixel_valuesinput_idsattention_mask

现在我们已准备好获取输出,只需将我们得到的inputs传递给模型。注意,我们需要添加**,因为我们传递的是一个包含参数的字典。

outputs = model(**inputs)
scores = outputs.logits
print(scores)

解读模型输出 📈

如你所见,这些数字目前没有明确意义,因为它们是模型的原始输出(logits)。为了将这些值转换为我们能理解的形式,我们需要将它们传递给一个softmax层。softmax层的输出将给出概率。

我们需要导入torch,然后将得到的分数传递给softmax层。

import torch
probs = torch.nn.functional.softmax(scores, dim=-1)
print(probs)

现在这个数字更有意义了。第一个值是图像和文本不匹配的概率,这个概率非常低。第二个值是匹配的概率。从数值来看,文本和图像确实以很高的概率匹配。

综上所述,我们可以说图像和文本以约98%的概率匹配。现在是暂停视频,尝试使用你自己的图像和提示词进行测试的好时机。

总结 🎯

本节课中,我们一起学习了如何使用BLIP多模态模型进行图像文本匹配。我们了解了多模态模型的概念,加载了特定的模型和处理器,准备了图像和文本输入,运行了模型,并通过softmax函数将模型的原始输出解读为可理解的匹配概率。在下一课中,我们将使用相同的模型但下载不同的权重,来完成图像描述生成任务。

012:图像描述生成

在本节课中,我们将学习如何使用Hugging Face的模型进行图像描述生成。我们将使用BLIP模型,并分别尝试有条件的图像描述和无条件的图像描述。

概述

图像描述生成任务要求模型根据输入的图像,生成一段描述该图像内容的文字。例如,对于一张图片,模型应能输出“一个男人和一只狗在一起看书”。我们还可以为模型提供一个起始文本,引导其生成特定开头的描述。

加载模型与处理器

首先,我们需要加载用于图像描述生成的模型和相应的处理器。我们将使用 transformers 库中的 BlipForConditionalGeneration 模型。

from transformers import BlipForConditionalGeneration, BlipProcessor

接下来,我们使用预训练的方法加载模型,并指定一个特定的检查点。

model = BlipForConditionalGeneration.from_pretrained("Salesforce/blip-image-captioning-base")

处理器的加载方式与模型类似。

processor = BlipProcessor.from_pretrained("Salesforce/blip-image-captioning-base")

准备图像

现在,我们有了执行图像描述生成的所有组件,只缺少图像本身和可选的引导文本。让我们先加载一张图像。我们将使用PIL库的 Image 类。

from PIL import Image

image = Image.open("path_to_your_image.jpg")

为了演示,我们假设加载的是一张女人和狗在海滩上的图片。

有条件的图像描述生成

有条件的图像描述生成意味着我们可以为模型提供一个文本,作为其输出描述的开头。例如,我们可以输入“A photograph of”。

首先,我们需要使用处理器来处理文本和图像。

text = "A photograph of"
inputs = processor(image, text, return_tensors="pt")

return_tensors="pt" 参数确保返回的是PyTorch张量。inputs 是一个字典,包含了 pixel_valuesinput_idsattention_mask 等参数。

现在,我们可以使用模型的 generate 方法来生成图像描述。

outputs = model.generate(**inputs)

outputs 是一个包含令牌ID(token IDs)的列表。为了将其解码为可读文本,我们需要调用处理器的 decode 方法。

caption = processor.decode(outputs[0], skip_special_tokens=True)
print(caption)

输出结果可能是:“a photograph of a woman and her dog on the beach”。

无条件的图像描述生成

无条件的图像描述生成意味着我们不提供任何起始文本,完全让模型自由发挥,从头开始生成描述。

这次,我们只将图像传递给处理器。

inputs = processor(image, return_tensors="pt")

然后,同样使用 generate 方法生成描述。

outputs = model.generate(**inputs)
caption = processor.decode(outputs[0], skip_special_tokens=True)
print(caption)

输出结果可能是:“a woman sitting on the beach with her dog”。

动手尝试

现在是一个很好的时机,你可以暂停视频,尝试上传自己的图片,并为模型提供不同的条件文本,观察生成结果的变化。

总结

在本节课中,我们一起学习了如何使用Hugging Face的BLIP模型进行图像描述生成。我们实践了两种方式:

  1. 有条件的图像描述生成:通过提供起始文本来引导模型输出。
  2. 无条件的图像描述生成:让模型完全自主地生成描述。

我们了解了如何加载模型和处理器,处理图像和文本输入,使用 generate 方法生成描述,以及解码令牌ID得到最终文本。

下一节课,我们将测试视觉问答任务,即向模型提问关于图像的问题,并让它返回答案。

013:多模态视觉问答 👁️🗨️

在本节课中,我们将学习如何利用Hugging Face的BLIP模型进行多模态视觉问答。我们将向模型展示一张图片,并提出一个关于图片内容的问题,模型将根据图像信息生成答案。

概述

上一节我们介绍了图像描述生成。本节中,我们来看看如何让模型根据图像内容回答具体问题。我们将复用BLIP模型,但这次是用于“视觉问答”任务。这意味着你可以给模型一张图片和一个问题,模型会分析图片并给出答案。

加载模型与处理器

与之前任务类似,执行视觉问答任务需要模型和处理器。以下是加载它们的步骤:

首先,从transformers库中导入用于视觉问答的BlipForQuestionAnswering类。

from transformers import BlipForQuestionAnswering

接着,使用.from_pretrained()方法加载预训练模型,并传入相关的模型检查点。

model = BlipForQuestionAnswering.from_pretrained("Salesforce/blip-vqa-base")

然后,我们加载处理器。同样从transformers库导入AutoProcessor类。

from transformers import AutoProcessor

使用相同的方法和检查点加载处理器。

processor = AutoProcessor.from_pretrained("Salesforce/blip-vqa-base")

准备输入数据

现在,我们需要加载待处理的图像,并将其与问题一起传递给处理器以生成模型输入。

我们将使用PIL库来加载图像。

from PIL import Image
image = Image.open("path/to/your/image.jpg")

假设我们加载的是一张“沙滩上的狗和女人”的图片。

执行视觉问答

接下来,我们可以向模型提出关于这张图片的问题。例如,我们可以问“图片中有多少只狗?”。

首先,使用处理器同时处理图像和文本问题,并返回PyTorch张量格式的输入。

inputs = processor(images=image, text="How many dogs are in the picture?", return_tensors="pt")

然后,将处理好的输入传递给模型的.generate()方法以获取输出。

outputs = model.generate(**inputs)

最后,使用处理器的.decode()方法将模型输出的张量解码为人类可读的文本答案。

answer = processor.decode(outputs[0], skip_special_tokens=True)
print(answer)  # 输出应为:1

模型正确地回答了图片中只有一只狗。

总结

本节课中我们一起学习了如何使用Hugging Face的BLIP模型进行多模态视觉问答。我们回顾了加载模型与处理器的步骤,学习了如何准备图像和文本输入,并实践了向模型提问并获取答案的完整流程。你可以尝试对同一张图片提出其他问题,或者上传自己的图片进行测试。在下一课,我们将学习使用OpenAI的CLIP模型进行零样本分类。

014:使用CLIP模型进行零样本图像分类 🖼️

在本节课中,我们将学习如何使用Hugging Face的CLIP模型进行零样本图像分类。零样本分类意味着模型能够根据你提供的任意标签列表来对图像进行分类,而无需针对特定类别进行额外的模型微调。

概述

上一节我们介绍了模型的基本加载。本节中,我们来看看如何利用CLIP模型执行零样本图像分类任务。CLIP是由OpenAI开发的多模态视觉-语言模型,它能够理解图像和文本之间的关联,从而实现无需特定训练的分类。

加载模型与处理器

与之前的课程类似,我们需要准备两样东西:模型本身和对应的处理器。

首先,我们从Transformers库中加载CLIP模型。我们使用from_pretrained方法,并传入适用于此任务的正确检查点。

from transformers import CLIPModel, CLIPProcessor

model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")

模型加载完成后,我们接着加载处理器。处理器负责将原始图像和文本标签转换为模型可以理解的格式。

processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")

准备图像与标签

现在,让我们准备一张待分类的图像。我们将使用PIL库来加载图像。

from PIL import Image
image = Image.open("path/to/your/image.jpg")

假设我们加载的图像是两只可爱的小猫。接下来,我们需要定义一组候选标签供模型选择。例如,我们可以创建以下两个标签:

  • a photo of a cat
  • a photo of a dog

执行分类推理

准备工作就绪后,我们可以开始进行分类了。以下是处理步骤:

首先,使用处理器同时处理图像和文本标签,生成模型所需的输入张量。

inputs = processor(text=["a photo of a cat", "a photo of a dog"], images=image, return_tensors="pt", padding=True)

接着,将处理好的输入传递给模型,得到输出结果。

outputs = model(**inputs)

模型的输出中,我们关注的是logits_per_image,它代表了图像与每个文本标签的匹配分数。为了得到概率值,我们需要对这些分数应用softmax函数。

import torch
probs = outputs.logits_per_image.softmax(dim=1)

现在,probs是一个概率张量。例如,它的值可能类似于tensor([[0.9999, 0.0001]])。这意味着模型认为图像是“猫”的概率接近100%,是“狗”的概率接近0%。

尝试与探索

你可以暂停视频,尝试以下操作来加深理解:

  • 更改标签列表,使用与图像内容无关的标签(例如“一辆汽车”、“一棵树”),观察模型的响应。
  • 上传一张全新的图像,并使用不同的标签组合进行测试。

总结

本节课中,我们一起学习了如何使用Hugging Face的CLIP模型进行零样本图像分类。我们完成了从加载模型、准备数据、执行推理到解读结果的全过程。关键在于理解CLIP作为一个多模态模型,能够直接计算图像与文本描述之间的相似度,从而实现灵活且强大的零样本分类能力。在下一节课中,我们将学习如何部署BLIP模型。

015:模型部署 🚀

概述

在本节课中,我们将学习如何利用Hugging Face Spaces将你的机器学习模型部署为可公开访问的演示应用和API。你将学会如何将本地运行的模型迁移到云端,使其无需依赖你的个人计算机即可持续运行。


创建Hugging Face Space

上一节我们介绍了Hugging Face生态系统中的各种任务。本节中我们来看看如何将你的应用部署到云端。

首先,你需要在Hugging Face网站(hf.co)上创建一个账户。登录后,在页面右上角点击“New Space”来创建一个新的空间。

以下是创建空间时需要填写的关键信息:

  • 空间名称:例如 blip-image-captioning-api
  • 许可证:可选择默认许可证
  • SDK:选择 Gradio
  • 硬件:选择 CPU basic
  • 可见性:设置为 Public 以便他人访问

创建完成后,你需要为该空间准备两个核心文件。


准备部署文件

空间创建后,需要配置运行环境。这主要通过两个文件实现。

1. requirements.txt 文件
此文件用于列出运行应用所需的所有Python库。

transformers
torch
gradio

2. app.py 文件
这是应用的主文件,包含了模型加载和Gradio界面的所有逻辑。

在编写部署代码前,最好先在本地进行测试。


本地测试与代码迁移

为了确保部署顺利,我们首先在本地Jupyter环境中测试应用的核心功能。

我们将使用 transformers 库的 pipeline 功能来加载BLIP图像描述模型,并用Gradio构建一个简单的交互界面。

from transformers import pipeline
import gradio as gr

# 加载图像描述管道,使用BLIP基础模型
image_to_text = pipeline("image-to-text", model="Salesforce/blip-image-captioning-base")

# 定义处理函数
def launch(image):
    # 使用全局定义的pipeline进行处理
    result = image_to_text(image)
    # 提取生成的描述文本
    return result[0]['generated_text']

# 创建Gradio界面
demo = gr.Interface(
    fn=launch,
    inputs=gr.Image(type="pil"),
    outputs="text"
)

# 启动界面,并生成可分享链接
demo.launch(share=True)

本地测试成功后,即可将 app.py 文件中的代码(移除 share=True 参数)复制到Hugging Face Space的 app.py 文件中。等待Space自动构建完成后,你的应用就上线了。


将Space用作API

应用部署成功后,其价值不仅在于交互界面,更在于可以作为一个API被其他程序调用。

在Space页面上,点击“Use via API”选项卡,可以获取调用该API的代码示例。

以下是调用API的基本步骤:

  1. 安装 gradio_client 库:pip install gradio_client
  2. 使用提供的链接实例化客户端。
  3. 调用 predict 方法并传入图像路径或URL。
from gradio_client import Client

client = Client("你的Space链接")
result = client.predict(
    "path/to/your/image.jpg", # 图像路径或URL
    api_name="/predict"
)
print(result)

你还可以通过 client.view_api() 方法查看API的详细结构,包括输入参数和返回类型。


高级功能:私有空间与GPU加速

除了公开部署,Hugging Face Spaces还支持更高级的用例。

部署私有模型
如果你希望部署的模型或应用不公开,可以将Space的可见性设置为 Private。调用私有API时,需要在客户端实例化时传入你的Hugging Face访问令牌。

client = Client("你的私有Space链接", hf_token="你的Hugging Face Token")

使用免费GPU资源(Zero GPU)
对于大型模型,CPU实例可能速度慢或内存不足。Hugging Face提供了免费的GPU资源(Zero GPU)。

使用方法如下:

  1. 访问 huggingface.co/zero-gpu-explorers 组织并申请加入。
  2. 申请通过后,创建新Space时,硬件选择中会出现 Zero GPU 选项。
  3. 选择该选项,即可在需要时自动获得GPU加速,非常适合运行大模型。

总结与探索

本节课中我们一起学习了如何利用Hugging Face Spaces进行模型部署。我们涵盖了从创建Space、准备文件、本地测试到最终部署上线的完整流程。你还学会了如何将部署的应用作为API调用,以及如何使用私有部署和免费GPU资源来满足更复杂的需求。

鼓励你浏览Hugging Face Spaces主页,探索“本周精选空间”,从中获取灵感,并将你在整个课程中学到的知识转化为可以轻松分享给朋友和同事的酷炫应用。


下一节:我们将对课程进行总结。

016:课程总结 🎉

在本节课中,我们将对这门关于Hugging Face开源模型的短期课程进行总结,回顾所学内容,并展望未来的学习与应用方向。


恭喜你完成了这门短期课程。在本课程中,你深入了解了如何为文本、音频和图像任务选择开源模型,这些模型都可以在Hugging Face Hub上找到。你构建了多个应用程序,例如聊天机器人、语音转录器和物体检测器等。现在,你掌握了如何使用Gradio为你的应用程序构建功能原型,以及如何通过Hugging Face Spaces快速部署它。

上一节我们介绍了模型部署,本节中我们来看看如何将所学知识融会贯通,并应用于更广阔的领域。

展望未来,你将能够:

  • 驾驭广阔的开源模型领域:你已具备在Hugging Face Hub上探索海量模型的能力。
  • 视现有流程为基础构建模块:可以将本课程中构建的各类应用流程视为基础组件。
  • 探索无限的创意机会:组合这些模块,创造新颖、独特的应用程序。创意空间无限。

这一切的实现,都离不开开源社区的协作精神。成千上万的人——包括研究人员、工程师、教育工作者和爱好者——通过以下方式为开源做出了贡献:

  • 在Hugging Face Hub上分享模型和数据集。
  • 向开源库提交合并请求。
  • 参与讨论,激发新想法。

我们今天见证的AI进步,很大程度上归功于开源社区。我们向所有为其进步做出贡献的人们致以诚挚的感谢。

我们鼓励你:

  • 探索Hugging Face Hub上可用的其他机器学习任务和模型。
  • 构建创新的应用程序。
  • 将你的创意与社区分享,以激励他人。

如果你觉得本课程有帮助,或许也可以与你的朋友分享。😊


本节课中我们一起学习了课程的核心收获,了解了开源社区的重要性,并获得了继续探索和创造的动力。希望你能运用这些知识,在AI的世界里构建出令人惊叹的应用。

posted @ 2026-03-26 08:11  绝不原创的飞龙  阅读(9)  评论(0)    收藏  举报