跳到主要内容

第一章 多媒体生成入门

生成式模型在近年来广泛流行。在阅读本文时,读者很可能已经在与生成模型进行过互动。或许是使用ChatGPT生成文本,或许是在Instagram等应用中使用风格转换,亦或是看过那些引发热议的深度伪造视频。这些都是生成式模型的实际应用!

在系列文章中,我们将探索生成式模型的世界,从两大生成模型阵营——transformers和扩散模型(diffusion)的基础开始,逐步深入到更高级的话题。我们将介绍不同类型的生成模型,它们的原理,以及如何使用。我们还将探讨生成式模型的伦理和社会影响以及它们在现实世界中的应用。本文中,我们会回顾一下走到今天这一步的历程,并了解一些模型所提供的功能,这些功能我们在后续会进行更深入的探讨。

那么,什么是生成式模型呢?从顶层来讲,它的基本思想是向模型提供数据进行训练,以便未来能生成与训练数据相似的新数据。例如,如果我用一个包含猫咪图像的数据集来训练模型,那么我可以使用这个模型生成新的猫咪图像,这些图像看起来就像是出自原始数据集。这是一个强大的概念,具有广泛的应用范围,从创建新奇的图像和视频到生成具有特定风格的文本。

在本系列文章中,有许多流行的工具方便我们轻松使用现有的模型。在机器学习的世界中,可以找到能公开访问的在大型数据集上训练的模型,任何人都可以使用这些模型。训练这样的模型通常需要大量的资金和时间,因此能够公开访问这些模型是条捷径。这些预训练模型可以用来生成新数据、对现有数据分类等等。我们甚至可以修改这些模型使用到新的场景中。最知名的开源模型平台之一是Hugging Face,上面有数百万个用于各种机器学习任务的模型(包括图像生成)。

本文相关代码请见GitHub仓库

文生图初体验

我们先以开源库diffusers开始举例。diffusers是一个知名库,提供了对最炙手可热的扩散模型的访问。它是一个强大而简单的工具箱,让我们能够快速加载和训练扩散模型!

通过访问Hugging Face Hub并筛选基于文生图像(text-to-image)的模型,我们可以找到一些最流行的模型,如Stable Diffusion和SDXL。我们将使用Stable Diffusion 1.5版本,这是一种能够生成高质量图像的扩散模型!进入模型页面,可以阅读模型卡片页,这是对于观测性和可重复性至关重要的文档。在这里,我们可以了解关于模型的信息,包括它是如何训练的,预期的使用场景等等。

有了模型(Stable Diffusion)和使用模型的工具(diffusers),就可以生成我们的第一张图像了!在加载模型时,需要将它们发送到具体的硬件设备,如CPU(cpu)、GPU(cuda或cuda:0)或称为Metal的Mac硬件(mps)。以下代码将频繁出现:它会对变量赋值cuda:0(如果有GPU可用);否则,则使用CPU。

import torch

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(f"Using device: {device}")

接下来,我们加载Stable Diffusion 1.5。diffusers 提供了名为StableDiffusionPipeline的高阶封装,非常适合这种情况。不必担心烦杂的参数——重点如下:

  • Stable Diffusion架构有许多模型,因此我们需要指定要使用的模型,本例中使用runwayml/stable-diffusion-v1-5
  • 我们需要指定加载模型时使用的精度。精度在之后会深入了解。从宏观上来看,生成模型由许多参数(数百万或数十亿个参数)组成。每个参数都是在训练期间学习到的一个数值,我们可以以不同精度存储这些参数(换句话说,使用更多的位数来存储模型)。较大的精度需要更多的内存和运算,通常也意味着更好的模型。而我们也可以通过torch_dtype=float16来设置较低的精度,使用比默认的float32更少的内存。

读者可能会希望了解variant参数。在某些代码库中,你可能会发现具有不同精度的多个检查点。当指定torch_dtype=float16时,我们下载默认模型(float32)并将其转换为float16。通过指定fp16变体,我们下载一个已经存储为float16精度的小检查点,下载它只需要一半的带宽和存储空间。检查你要用代码储库,看看是否有多个精度变体!

初次运行此代码时可能会花费一些时间:管道需要下载好几个GB的模型!如若是第二次加载管道,仅在Hugging Face上托管模型的远程库发生变化时,才会重新下载模型。Hugging Face库将模型放在本地缓存中,这样后续加载速度更快。

from diffusers import StableDiffusionPipeline

pipe = StableDiffusionPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5",
torch_dtype=torch.float16,
variant="fp16",
).to(device)
Loading pipeline components...:   0%|          | 0/7 [00:00<?, ?it/s]
`text_config_dict` is provided which will be used to initialize `CLIPTextConfig`. The value `text_config["id2label"]` will be overriden.

此时模型已经加载好了,我们可以定义一个提示词(prompt),也即模型将接收的文本输入。然后将提示词传递给模型,根据该文本生成一张图像!

prompt = "a photograph of an astronaut riding a horse"
pipe(prompt).images[0]
0%|          | 0/50 [00:00<?, ?it/s]

a photograph of an astronaut riding a horse

太神奇了!只需几行代码,我们就生成了一张新奇的图像。放松时间到,用不同的提示词生成新图像。可以注意到生成的图像会有不同程度的改进。在后续文章中,我们将探讨如何细颗粒度地控制生成过程,以及最新的具有更好生成能力的一些模型。

  • 第四章和第五章深入探讨扩散模型背后的所有组件,以及如何用文本生成新的图像。在此之前,第三章介绍了一些方法,如自动编码器(autoencoders),这些方法可以从输入数据中学习有效标记,减少构建扩散模型及其他生成模型的算力需求。
  • 在第七章中,我们将学习如何向Stable Diffusion传授新概念。例如,我们可以教Stable Diffusion“my dog”这个概念,在场景中生成作者狗狗的图像,如“狗狗登上月球”。
  • 第八章展示了扩散模型不仅可用于图像生成,还可以通过提示词编辑图像或填充图像的空白部分。

文生文初体验

正如diffusers是一个非常便捷的扩散模型库,大名鼎鼎的transformers库在运行基于转换器的模型和适应新用例方面也极具价值。它为广泛的任务提供了标准化接口,例如生成文本、检测图像中的对象以及将音频文件转录为文本。

transformers库提供了不同层次的抽象。例如,如果不关心内部细节,最简单的方法是使用pipeline,它抽象了获取预测所需的所有处理过程。我们可以通过调用pipeline()函数并指定我们想要解决的任务(如文本分类text-classification)来实例化一个管道。

from transformers import pipeline

classifier = pipeline("text-classification")
classifier("This movie is disgustingly good !")
[{'label': 'POSITIVE', 'score': 0.9998536109924316}]

模型正确地预测了输入文本中的情感是正向的。默认,文本分类管道使用的是一个情感分析模型,但我们也可以指定其他基于transformers的文本分类模型。

同样,我们可以将任务切换为文本生成(text-generation),通过它我们可以通过输入提示词生成新的文本。默认管道使用GPT-2模型。

generator = pipeline("text-generation")
prompt = "It was a dark and stormy"
generator(prompt)[0]["generated_text"]
'It was a dark and stormy morning — dark clouds, mist, light and frost, and dark clouds with a thousand voices and with a thousand mouths and a thousand faces. The stars were the moon, the stars were the moon, and the stars'

虽然按照今天的标准,GPT-2算不上好模型,但它为我们提供了一个使用小模型初步了解transformers生成能力的机会。我们学习到的关于GPT-2的概念适用于诸如Llama或Mistral等一些(在撰写本文时)最强大的开源模型。在整个系列中,我们会平衡模型的质量和大小。通常,较大的模型会有更高质量的生成。同时,我们希望拥有消费级电脑或可以访问免费服务的人能够通过运行代码来做新的生成。

  • 第二章讲解transformer模型的工作原理。我们将深入探讨不同类型的变压器模型,以及如何使用它们生成文本。
  • 第五章介绍如何使用自有数据继续训练transformer模型以适应不同的用例。这样我们能够制作出类似于ChatGPT或Bard中的对话模型。我们还会讨论高效的训练方法,以便能在自己的电脑上进行训练!

文生音频初体验

生成式模型不仅限于图像和文本,还可以生成视频、短歌、合成语音、蛋白质结构提案等!

第九章深入探讨可以通过机器学习解决的音频相关任务,例如转录会议内容和生成音效!当前,我们可以使用我们熟悉的transformers管道,并使用由Meta发布的MusicGen小版本模型,根据文本生成音乐。

注:本地运行MusicGen要求🤗 Transformers的版本不小于4.31.0。

synthesiser = pipeline("text-to-audio", "facebook/musicgen-small")

music = synthesiser("electric rock solo, very intense", forward_params={"do_sample": True})
print(music )
{'audio': array([[[-0.01494718, -0.02395139,  0.01935647, ..., -0.03298454,
-0.04028149, -0.0330082 ]]], dtype=float32), 'sampling_rate': 32000}

稍后,我们将学习音频数据是如何表示的以及这些数值代表什么。当然,我们无法直接在显示音频文件!最好的替代方法是在我们的笔记本中显示一个播放器,或将音频保存到一个文件中,以便我们使用自己喜欢的音频程序进行播放。例如,我们可以使用+IPython.display+来进行实现!

import IPython.display as ipd 
display(ipd.Audio(music["audio"][0], rate=music["sampling_rate"]))

electric rock solo, very intense

伦理和社会效应

虽然生成模型提供了卓越的能力,但它们的广泛使用引发了关于伦理和社会影响的关切。在我们深挖生成模型的能力时,一定要牢记这些问题。以下是几个要重点关注的领域:

  • 隐私和许可:生成式模型通过少量数据生成逼真的图像和视频的能力对隐私提出了重大挑战。例如,用个人的小部分真实图像创建合成图像会导致未经许可使用个人数据的问题。这也增加了深度伪造(deepfake)的风险,进而被用于传播虚假信息或伤害个人。
  • 偏见和公平:生成式模型是在带有偏见的大型数据集上训练的。这些偏见可能被生成模型继承和放大,我们将在第二章中探讨这一问题。例如,用于训练图像生成模型的偏见数据集可能会生成刻板印象或歧视性的图像。弱化这些偏见并确保生成模型的公平和不违背伦理的使用是很重要的。
  • 监管:鉴于生成式模型的潜在风险,越来越多的人呼吁监管的介入和问责机制的建立,以保障负责任地开发和使用。这包括透明度要求、伦理指南和法律框架,来解决生成模型的滥用问题。

在探索这些模型的能力时,要以谨慎和符合伦理的心态对待生成式模型。我们将在本系列中思考这些道德影响以及如何负责任地使用模型。

我们的历程和现状

生成式模型始于几十年前,最初专注于基于规则的系统。随着算力和数据的增加,生成式模型演变为使用统计方法和机器学习。随着深度学习成为机器学习强大范式以及图像和语音识别领域的突破,生成式模型取得了显著进展。虽然在几十年前就已发明卷积神经网络(CNN)和循环神经网络(RNN),但在过去十年中才得以广泛流行。CNN革命性地改变了图像处理任务,RNN提供了序列数据建模能力,使得文本翻译和文本生成等任务成为可能。

2014年,伊恩·古德费洛(Ian Goodfellow)带来了生成对抗网络(GAN),以及诸如DCGAN、条件GAN等变体,开启了生成式模型的新纪元。GAN被用于生成高质量的图像,并应用于样式转换等任务,使用户能够以惊人的逼真度将艺术风格应用于他们的图像。尽管非常强大,但近年来扩散模型在质量上已然超越GAN。

类似地,尽管RNN曾是语言模型的首选工具,但transformer模型(包括GPT等架构)在自然语言处理方面达到了最先进的表现。这些模型在语言理解、文本生成和机器翻译等任务中展示了卓越的能力,超越了以前的基准并设定了新的NLP性能标准。特别是GPT,由于其生成连贯且上下文相关文本的能力,变得极为流行。不久之后,一大波生成式语言模型涌现!

生成式AI始于能够生成随机数据(如随机图像或文本)的简单模型。随着时间的推移,深度学习的发展和生成模型能够生成高度逼真和复杂的数据,这个领域取得了显著进展。我们见证了GAN等模型的出现,它们可以生成高质量的图像,以及transformer,可以生成连贯且上下文相关的文本。我们还见证了像DALL·E和Stable Diffusion这类模型的发展,它们可以根据文本提示词生成图像。

近年来,随着研究、资源和生成式AI开发的快速展开,越来越多的社区对该领域感兴趣,开源生态系统和优化部署的研究,使得生成式AI比以往任何时候都更容易获取到,带来了广泛的应用和使用案例。2023年至2024年间,我们见证了一代新的模型,它们可以生成高质量的图像、文本、代码、视频等;包括ChatGPT、DALL·E、Imagen、Stable Diffusion、Llama、Mistral等。

生成式AI模型是如何训练的?大资金投入和开源

在过去几年中,我们目睹的最令人印象深刻的生成式模型大多由大厂的重要实验室发布。OpenAI开发了ChatGPT、DALL·E和Sora;谷歌构建了Imagen、Bard和Gemini;Meta创建了Llama和Code Llama。发布方式具有不同程度的开放性。有些可以通过特定的用户界面使用,有些可以通过开发者API访问,有些只是作为研究报告公布,根本没有公开访问权限。有时,也会发布代码和模型权重:这些通常被称为开源发布,因为这些是在你硬件上运行模型所需的基本工具。但出于战略原因,经常隐而不发。

与此同时,一个不断增长、充满活力和热情的社区将开源模型作为其创造积木。研究人员、工程师、测试和业余爱好者等各类从业者在彼此的工作之上进行构建,提出新颖的解决方案和聪明的想法,一步步推动这个领域的发展。其中一些想法最终会进入理论知识体系,研究人员可以从中汲取灵感,随后开发出新模型。

即便是非开源的大模型,也能为社区提供灵感,其工作的成果将惠及业界。

有这种迭代是因为有些模型是开源的并且可以被社区使用。发布开源模型的公司并不是出于利他主义,而是因为它们在这种策略中看到了经济价值。通过提供被社区采用的代码和模型,它们获得了公共审查、bug修复、新想法、派生模型架构,甚至是与发布的模型配合良好的新数据集。由于所有这些贡献都基于它们发布的资产,这些公司可以快速采 纳,从而比独自开发更快。Meta发布Llama时,一个繁荣的生态系统自然而然地围绕它成长起来。包括Meta、Stability AI(Stable Diffusion)和Mistral AI在内的老牌和新兴公司都在不同程度上将开源作为其商业战略的一环。这和那些更喜欢将其商业秘密保密的公司(即使这些公司也可以从开源社区中汲取灵感)一样是合理的策略。

在这点上,需要澄清模型发布很少是真正的开源。与软件世界不同,源代码不足以完全理解机器学习系统。模型权重也不够:它们只是模型训练过程的最终输出。要能够精确复制现有模型,需要训练模型所使用的源代码(不止是建模代码或推理代码),训练方案和参数,以及最重要的是所有用于训练的数据。这些通常都不会发布,尤其是数据。如果能访问这些细节,社区和公众将能够理解模型的工作原理,探讨可能影响它的偏见,并更好地评估其优点和局限性。权重和模型代码提供了对这部分的不完整预估,但实际的数据会更好。即使模型是公开发布的,它们通常也带有一个特别的许可证,不符合开源界的开放源码定义。这并不是说这些模型没有用,或者发布它们的公司不在做好事,但这是一个重要的背景,需要牢记,这也是为什么我们经常说公开访问而不是开源的原因之一。

无论如何,现在是构建生成式模型或使用生成式模型的最佳时机。你不需要是顶尖研究实验室的工程师就可以提出解决感兴趣的问题的想法,或者如果你有意愿,就可以为这个领域做出贡献。希望这一剖解对你益!

前景展望

希望在生成了你的第一张图像、音频和文本之后,读者会对学习扩散和transformer的工作原理、如何让它们适配新的用例以及如何将它们用于不同的创意应用感兴趣。尽管本章侧重于顶层工具,但我们将建立扎实的基础和直觉,了解这些模型的工作原理,让我们一起踏上生成式之旅吧。下一章继续学习transformer模型的原理!