生成式神经网络全解析:从GAN/VAE到Diffusion Model,解锁AIGC创意生成(附Stable Diffusion实战代码)
作为AI技术专家兼学习规划博主,我经常收到开发者的提问:“南木,想做图像生成,该选GAN还是VAE?“Diffusion Model为什么能生成比GAN更细腻的图?“Stable Diffusion的文本引导是怎么实现的?能不能自己跑通代码?
作为AI技术专家兼学习规划博主,我经常收到开发者的提问:
“南木,想做图像生成,该选GAN还是VAE?”
“Diffusion Model为什么能生成比GAN更细腻的图?”
“Stable Diffusion的文本引导是怎么实现的?能不能自己跑通代码?”
生成式AI(AIGC)的核心魅力,在于让机器从“识别数据”走向“创造数据”——从早期VAE生成模糊的低分辨率图像,到GAN实现高保真人脸生成,再到Diffusion Model掀起文本生成图像(Text-to-Image)的浪潮,生成式模型的每一次迭代,都在突破“机器创意”的边界。
这篇文章会以“技术演进+原理拆解+实战落地”为脉络,系统讲解三大主流生成式模型(VAE、GAN、Diffusion Model):从核心思想、数学原理,到优缺点对比,最后聚焦工业级应用——用PyTorch+Diffusers库实现Stable Diffusion的文本生成图像、图像优化、模型微调。全程贯穿“公式推导+代码注释+结果分析”,既适合初学者入门,也能为开发者提供实战参考。
同时需要学习规划、就业指导、技术答疑和系统课程学习的同学 欢迎扫码交流
一、生成式模型的核心目标:从“概率分布”到“创意生成”
在拆解具体模型前,我们先明确一个核心问题:生成式模型到底在做什么?
简单来说,生成式模型的目标是“学习真实数据的概率分布,然后从该分布中采样,生成新的、与真实数据相似的样本”。比如:
- 图像生成:学习“真实猫图片”的分布,生成新的、不存在但逼真的猫图片;
- 文本生成:学习“人类语言”的分布,生成通顺、有逻辑的句子;
- 多模态生成:学习“文本-图像”的联合分布,根据文本描述(如“一只坐在月球上的兔子”)生成对应图像。
传统判别式模型(如CNN分类器、Transformer文本分类)只关注“判断样本属于哪个类别”,而生成式模型需要“还原数据的全貌”——这也是生成式模型更复杂、但应用场景更广阔的原因。
接下来,我们按“技术演进顺序”,逐个拆解VAE、GAN、Diffusion Model这三大里程碑式的生成模型。
二、生成式模型的“先行者”:VAE(变分自编码器)
VAE(Variational Autoencoder,变分自编码器)是2013年由Kingma和Welling提出的生成模型,核心思想是“通过自编码器结构,结合变分推断,学习数据的潜在概率分布”。它是第一个能稳定生成多样化样本的模型,为后续生成式模型奠定了基础。
2.1 VAE的核心思想:“概率化”的自编码器
传统自编码器(Autoencoder)由“编码器(Encoder)”和“解码器(Decoder)”组成:
- 编码器:将高维输入(如28×28的MNIST图像)压缩为低维 latent 向量(如10维);
- 解码器:将 latent 向量解压,还原为与输入维度一致的输出;
- 训练目标:最小化“输入与输出的重构误差”(如MSE)。
但传统自编码器有个致命缺陷:latent 空间不连续,无法用于生成新样本——比如随机采样一个 latent 向量,解码器可能生成无意义的图像。
VAE的改进在于:将 latent 向量的生成“概率化”——不再让编码器输出确定的 latent 向量,而是输出 latent 向量的“均值(μ)”和“方差(σ²)”,然后从该正态分布中随机采样得到 latent 向量。这样一来,latent 空间是连续的,任意采样的 latent 向量都能生成有意义的样本。
2.2 VAE的结构与数学原理:3步理解生成过程
VAE的生成过程可分为“编码-采样-解码”三步,配合“重构损失+KL散度损失”训练,确保生成样本既逼真又多样。
步骤1:编码(Encoder):输出 latent 分布的参数
编码器接收输入样本 ( x )(如图像),通过神经网络(如CNN)输出两个向量:
- 均值向量 ( \mu(x) ):维度为 ( d_{\text{latent}} )(如10);
- 对数方差向量 ( \log\sigma^2(x) )(用对数避免方差为负)。
公式表示:
μ,logσ2=Encoder(x) \mu, \log\sigma^2 = \text{Encoder}(x) μ,logσ2=Encoder(x)
步骤2:采样(Reparameterization Trick):从 latent 分布中采样
为了让 latent 向量的采样过程可微分(便于反向传播),VAE引入“重参数化技巧”:
先从标准正态分布 ( \mathcal{N}(0,1) ) 中采样一个噪声向量 ( \epsilon ),再通过以下公式得到 latent 向量 ( z ):
z=μ+σ⋅ϵ z = \mu + \sigma \cdot \epsilon z=μ+σ⋅ϵ
其中 ( \sigma = \exp(\log\sigma^2 / 2) )(将对数方差转为方差,再开方得到标准差)。
为什么需要重参数化?
如果直接采样 ( z \sim \mathcal{N}(\mu, \sigma^2) ),采样过程是随机的,梯度无法从 ( z ) 回传至编码器参数;而重参数化后,随机性转移到 ( \epsilon )(与模型参数无关),梯度可通过 ( \mu ) 和 ( \sigma ) 回传。
步骤3:解码(Decoder):从 latent 向量生成样本
解码器接收采样得到的 latent 向量 ( z ),通过神经网络(如反卷积CNN)生成与输入 ( x ) 维度一致的输出 ( \hat{x} )(生成样本)。
公式表示:
x^=Decoder(z) \hat{x} = \text{Decoder}(z) x^=Decoder(z)
步骤4:VAE的损失函数:重构误差+KL散度
VAE的训练目标是“让生成样本 ( \hat{x} ) 既像真实样本(重构误差小),又让 latent 分布接近标准正态分布(KL散度小)”,损失函数为两者之和:
LVAE=Lrecon+β⋅LKL \mathcal{L}_{\text{VAE}} = \mathcal{L}_{\text{recon}} + \beta \cdot \mathcal{L}_{\text{KL}} LVAE=Lrecon+β⋅LKL
-
重构误差(( \mathcal{L}_{\text{recon}} )):衡量生成样本与真实样本的差异,根据样本类型选择损失函数:
- 图像(连续值,如MNIST灰度图):用均方误差(MSE):
Lrecon=1N∑i=1N∥xi−x^i∥2 \mathcal{L}_{\text{recon}} = \frac{1}{N} \sum_{i=1}^N \| x_i - \hat{x}_i \|^2 Lrecon=N1i=1∑N∥xi−x^i∥2 - 图像(离散值,如RGB图):用交叉熵损失(CE):
Lrecon=−∑i=1Nxilogx^i \mathcal{L}_{\text{recon}} = -\sum_{i=1}^N x_i \log\hat{x}_i Lrecon=−i=1∑Nxilogx^i
- 图像(连续值,如MNIST灰度图):用均方误差(MSE):
-
KL散度(( \mathcal{L}_{\text{KL}} )):衡量 latent 分布 ( \mathcal{N}(\mu, \sigma^2) ) 与标准正态分布 ( \mathcal{N}(0,1) ) 的差异,强制 latent 空间连续、可采样。
数学上可推导出闭式解(无需数值积分):
LKL=12∑i=1dlatent(μi2+σi2−logσi2−1) \mathcal{L}_{\text{KL}} = \frac{1}{2} \sum_{i=1}^{d_{\text{latent}}} \left( \mu_i^2 + \sigma_i^2 - \log\sigma_i^2 - 1 \right) LKL=21i=1∑dlatent(μi2+σi2−logσi2−1) -
超参数 ( \beta ):平衡重构误差和KL散度,( \beta ) 越大,latent 分布越接近标准正态分布(多样性强,但重构质量可能下降);( \beta ) 越小,重构质量越高(但多样性可能不足)。
2.3 VAE的优缺点与适用场景
优势 | 劣势 |
---|---|
1. latent 空间连续可解释:任意采样 latent 向量都能生成有意义的样本,支持插值生成(如“猫→狗”的渐变图); 2. 训练稳定:无对抗过程,只需最小化损失函数,不易出现模式崩溃; 3. 概率生成:天然支持不确定性建模(如生成多个版本的同一输入)。 |
1. 生成质量低:受限于重构误差,生成图像通常模糊(如MNIST清晰,但高分辨率图像模糊); 2. latent 空间利用率低:部分 latent 维度对生成结果影响小,存在冗余; 3. 缺乏细节控制:无法精准控制生成样本的局部细节(如“让猫的眼睛变成蓝色”)。 |
适用场景:低计算成本的生成任务(如低分辨率图像生成、数据增广、异常检测),或需要 latent 空间插值的场景(如风格迁移的中间过渡效果)。
三、生成式模型的“革命者”:GAN(生成对抗网络)
GAN(Generative Adversarial Network,生成对抗网络)是2014年由Goodfellow提出的生成模型,核心思想是“通过生成器与判别器的零和博弈,迫使生成器学习真实数据的分布”。GAN彻底改变了生成式模型的范式,首次实现了高保真图像生成,成为AIGC早期的核心技术。
3.1 GAN的核心思想:“造假者与鉴宝师”的博弈
GAN的结构像一场“对抗游戏”,包含两个核心角色:
- 生成器(Generator,G):“造假者”,输入随机噪声 ( z )(如100维),通过神经网络(如反卷积CNN)生成假样本 ( G(z) )(如64×64的人脸图像);
- 判别器(Discriminator,D):“鉴宝师”,输入样本(真实样本 ( x ) 或假样本 ( G(z) )),通过神经网络(如CNN)输出“样本为真实数据的概率” ( D(x) )(范围0~1)。
训练目标:
- 判别器 ( D ):尽量区分真实样本和假样本,即 ( D(x) \to 1 )(真实样本判为真),( D(G(z)) \to 0 )(假样本判为假);
- 生成器 ( G ):尽量欺骗判别器,让判别器无法区分假样本和真实样本,即 ( D(G(z)) \to 1 )(假样本判为真)。
这场博弈的最终平衡点是:生成器生成的假样本与真实样本无法区分(( D(G(z)) = 0.5 )),判别器无法提升性能——此时生成器已完全学习到真实数据的分布。
3.2 GAN的数学原理: minimax 博弈与损失函数
GAN的训练过程是“极小极大(minimax)优化问题”,目标函数如下:
minGmaxDL(D,G)=Ex∼pdata(x)[logD(x)]+Ez∼pz(z)[log(1−D(G(z)))] \min_G \max_D \mathcal{L}(D, G) = \mathbb{E}_{x \sim p_{\text{data}}(x)} \left[ \log D(x) \right] + \mathbb{E}_{z \sim p_z(z)} \left[ \log (1 - D(G(z))) \right] GminDmaxL(D,G)=Ex∼pdata(x)[logD(x)]+Ez∼pz(z)[log(1−D(G(z)))]
- ( p_{\text{data}}(x) ):真实数据的分布;
- ( p_z(z) ):随机噪声的分布(通常为标准正态分布或均匀分布);
- ( \mathbb{E} ):期望操作。
1. 判别器的损失(最大化 ( \mathcal{L}(D, G) ))
判别器的目标是“正确区分真实样本和假样本”,损失可拆分为两部分:
- 真实样本损失:( \log D(x) )——希望 ( D(x) ) 越大,该项越大;
- 假样本损失:( \log (1 - D(G(z))) )——希望 ( D(G(z)) ) 越小,该项越大。
实际训练中,常用“二元交叉熵(BCE)”损失实现,公式如下:
LD=−1N[∑x∈真实样本logD(x)+∑z∈噪声log(1−D(G(z)))] \mathcal{L}_D = -\frac{1}{N} \left[ \sum_{x \in \text{真实样本}} \log D(x) + \sum_{z \in \text{噪声}} \log (1 - D(G(z))) \right] LD=−N1[x∈真实样本∑logD(x)+z∈噪声∑log(1−D(G(z)))]
2. 生成器的损失(最小化 ( \mathcal{L}(D, G) ))
生成器的目标是“欺骗判别器”,损失为假样本损失的相反数(因为生成器希望 ( \log (1 - D(G(z))) ) 越小越好):
LG=−1N∑z∈噪声logD(G(z)) \mathcal{L}_G = -\frac{1}{N} \sum_{z \in \text{噪声}} \log D(G(z)) LG=−N1z∈噪声∑logD(G(z))
为什么不用原目标中的 ( \log (1 - D(G(z))) )?
训练初期,生成器生成的假样本质量差,( D(G(z)) \approx 0 ),此时 ( \log (1 - D(G(z))) \approx 0 ),梯度接近0,生成器难以更新(“梯度消失”问题)。改用 ( -\log D(G(z)) ) 后,当 ( D(G(z)) \approx 0 ) 时,损失很大,梯度充足,生成器能快速学习。
3.3 GAN的改进:从原始GAN到WGAN-GP
原始GAN存在两大致命问题,限制了其工业应用:
- 训练不稳定:生成器和判别器的能力难以平衡,常出现一方“碾压”另一方的情况(如判别器过强,生成器梯度消失;生成器过强,判别器无法区分);
- 模式崩溃(Mode Collapse):生成器只生成少数几种“高逼真度”样本,缺乏多样性(如生成人脸时,所有脸都是同一种发型、肤色)。
为解决这些问题,研究者提出了多种改进方案,其中WGAN-GP(Wasserstein GAN with Gradient Penalty) 是最经典、应用最广的改进版本。
WGAN-GP的核心改进:
-
用Wasserstein距离替代JS散度:
原始GAN用JS散度衡量“真实分布与生成分布的差异”,但JS散度在分布不重叠时为常数,导致梯度消失;Wasserstein距离(Earth-Mover距离)能更平滑地衡量分布差异,即使分布不重叠,也能提供稳定梯度。 -
引入梯度惩罚(Gradient Penalty):
强制判别器的梯度范数不超过1(满足Lipschitz连续条件),避免判别器过强,同时防止模式崩溃。梯度惩罚项加入判别器损失后,公式如下:
LDWGAN-GP=LD+λ⋅Ex^∼px^[(∥∇x^D(x^)∥2−1)2] \mathcal{L}_{D_{\text{WGAN-GP}}} = \mathcal{L}_D + \lambda \cdot \mathbb{E}_{\hat{x} \sim p_{\hat{x}}} \left[ \left( \|\nabla_{\hat{x}} D(\hat{x})\|_2 - 1 \right)^2 \right] LDWGAN-GP=LD+λ⋅Ex^∼px^[(∥∇x^D(x^)∥2−1)2]
其中 ( \hat{x} ) 是“真实样本与假样本之间的插值样本”,( \lambda ) 是惩罚系数(通常取10)。
3.4 GAN的优缺点与适用场景
优势 | 劣势 |
---|---|
1. 生成质量高:能生成高分辨率、细节丰富的样本(如1024×1024的人脸、风景图); 2. 生成速度快:直接从噪声生成样本,无需逐步去噪(比Diffusion Model快1~2个数量级); 3. 可控性强:通过条件GAN(如cGAN)可精准控制生成样本的属性(如“生成男性、黑发、微笑的人脸”)。 |
1. 训练不稳定:需精细调整超参数(如学习率、批次大小),否则易出现梯度消失或模式崩溃; 2. 缺乏概率解释:latent 空间不连续,无法量化生成样本的不确定性; 3. 多模态生成弱:难以处理文本-图像等多模态输入,文本引导能力远不如Diffusion Model。 |
适用场景:高保真单模态生成任务(如人脸生成、风格迁移、图像修复),或对生成速度有要求的场景(如实时图像生成)。
四、生成式模型的“当前王者”:Diffusion Model(扩散模型)
Diffusion Model(扩散模型)是2015年提出、2020年后爆发的生成模型,核心思想是“通过逐步向真实样本添加噪声,再学习逐步去除噪声的过程,实现样本生成”。它完美解决了VAE的模糊问题和GAN的训练不稳定问题,成为当前AIGC的主流技术(如Stable Diffusion、MidJourney、DALL-E 2均基于Diffusion Model)。
4.1 Diffusion Model的核心思想:“逐步加噪-逐步去噪”
Diffusion Model的灵感来自物理学中的“扩散过程”——比如墨滴在水中的扩散:墨滴(真实样本)会逐渐扩散到水中,最终变成均匀的噪声;反之,如果能逆转这个过程,均匀噪声也能逐步恢复为墨滴。
Diffusion Model将这个过程分为两个阶段:
- 前向扩散(Forward Diffusion):在T步内,逐步向真实样本 ( x_0 ) 添加高斯噪声,得到一系列噪声样本 ( x_1, x_2, …, x_T ),最终 ( x_T ) 接近纯高斯噪声;
- 反向扩散(Reverse Diffusion):训练一个“去噪模型(Denoiser)”,学习从噪声样本 ( x_t ) 恢复出前一步的样本 ( x_{t-1} ),最终从纯噪声 ( x_T ) 出发,经过T步去噪,生成真实样本 ( x_0 )。
4.2 Diffusion Model的数学原理:DDPM的基础框架
Diffusion Model的经典实现是DDPM(Denoising Diffusion Probabilistic Models,去噪扩散概率模型),我们以DDPM为例,拆解前向扩散和反向扩散的数学过程。
阶段1:前向扩散(Forward Process):可控的加噪
前向扩散是一个固定、无需训练的过程,每一步加噪都遵循高斯分布,且满足“马尔可夫性”(即 ( x_t ) 只依赖 ( x_{t-1} ))。
为了让加噪过程可控,DDPM定义了一个“噪声调度表”——一系列逐渐增大的噪声系数 ( \beta_1, \beta_2, …, \beta_T )(通常 ( \beta_1 \approx 10^{-4} ),( \beta_T \approx 0.02 )),并衍生出以下参数:
- ( \alpha_t = 1 - \beta_t ):每一步的“保真性系数”(( \alpha_t ) 越小,加噪越强);
- ( \bar{\alpha}t = \prod{i=1}^t \alpha_i ):前t步的累积保真性系数(( \bar{\alpha}_t ) 随t增大而减小,( \bar{\alpha}_T \approx 0 ))。
每一步加噪的公式为:
xt=αˉt⋅x0+1−αˉt⋅ϵ x_t = \sqrt{\bar{\alpha}_t} \cdot x_0 + \sqrt{1 - \bar{\alpha}_t} \cdot \epsilon xt=αˉt⋅x0+1−αˉt⋅ϵ
其中 ( \epsilon \sim \mathcal{N}(0, I) ) 是高斯噪声。
关键特性:任意步骤t的样本 ( x_t ) 都可由原始样本 ( x_0 ) 直接生成(无需逐步加噪),这为反向扩散的训练提供了便利。
阶段2:反向扩散(Reverse Process):可学习的去噪
反向扩散是需要训练的过程,目标是学习从 ( x_t ) 恢复 ( x_{t-1} ) 的条件分布 ( p(x_{t-1} | x_t) )。DDPM假设该分布是高斯分布:
p(xt−1∣xt)=N(xt−1;μθ(xt,t),σt2I) p(x_{t-1} | x_t) = \mathcal{N}(x_{t-1}; \mu_\theta(x_t, t), \sigma_t^2 I) p(xt−1∣xt)=N(xt−1;μθ(xt,t),σt2I)
其中:
- ( \mu_\theta(x_t, t) ):高斯分布的均值,由去噪模型 ( \theta ) 预测;
- ( \sigma_t^2 ):高斯分布的方差,通常固定为 ( \beta_t ) 或由噪声调度表计算(无需训练)。
阶段3:去噪模型的训练:预测噪声而非直接生成
直接预测 ( x_{t-1} ) 难度较大,DDPM采用了更巧妙的策略:让去噪模型预测“前向扩散过程中添加的噪声 ( \epsilon )”——因为根据前向扩散公式,( x_0 ) 可由 ( x_t ) 和 ( \epsilon ) 推导得到:
x0=1αˉt(xt−1−αˉt⋅ϵ) x_0 = \frac{1}{\sqrt{\bar{\alpha}_t}} \left( x_t - \sqrt{1 - \bar{\alpha}_t} \cdot \epsilon \right) x0=αˉt1(xt−1−αˉt⋅ϵ)
训练目标是“最小化模型预测的噪声 ( \epsilon_\theta(x_t, t) ) 与真实噪声 ( \epsilon ) 的MSE损失”:
LDDPM=Ex0,ϵ,t[∥ϵ−ϵθ(xt,t)∥2] \mathcal{L}_{\text{DDPM}} = \mathbb{E}_{x_0, \epsilon, t} \left[ \| \epsilon - \epsilon_\theta(x_t, t) \|^2 \right] LDDPM=Ex0,ϵ,t[∥ϵ−ϵθ(xt,t)∥2]
为什么预测噪声?
- 噪声是加性的,预测难度低于直接预测样本;
- 噪声与样本维度一致,损失计算简单(MSE即可);
- 可通过噪声间接推导样本,保证生成过程的稳定性。
4.3 Stable Diffusion的创新:让Diffusion Model走向实用
DDPM虽然能生成高质量样本,但存在一个致命缺陷:计算成本极高——需要在高维像素空间(如512×512×3=786432维)进行T步(如1000步)扩散,普通GPU无法承受。
Stable Diffusion(2022年由Stability AI提出)通过两大创新,将Diffusion Model的计算成本降低了两个数量级,使其能在消费级GPU上运行:
创新1:Latent Diffusion( latent 空间扩散)
Stable Diffusion引入“自动编码器(VAE)”,将高维像素空间的扩散转移到低维 latent 空间:
- 编码阶段:用VAE的编码器将512×512×3的图像压缩为64×64×4的 latent 向量(维度从786432降至16384,压缩率48倍);
- 扩散阶段:在 latent 空间进行T步(如50步)扩散(加噪+去噪),计算成本大幅降低;
- 解码阶段:用VAE的解码器将去噪后的 latent 向量解压为512×512×3的图像。
创新2:文本引导(Text Guidance):Cross-Attention机制
Stable Diffusion通过“文本编码器(如CLIP ViT-L/14)”和“Cross-Attention机制”,实现“文本描述控制图像生成”:
- 文本编码:用CLIP将文本描述(如“a photo of an astronaut riding a horse on mars”)编码为77维的文本嵌入向量(text embedding);
- Cross-Attention:在去噪模型(U-Net)中加入Cross-Attention层,让 latent 空间的去噪过程“关注文本嵌入中的关键信息”(如“astronaut”“horse”“mars”);
- 条件生成:通过“Classifier-Free Guidance(CFG)”超参数控制文本引导强度——CFG越大,生成图像与文本的匹配度越高(但可能损失多样性)。
4.4 Diffusion Model的优缺点与适用场景
优势 | 劣势 |
---|---|
1. 生成质量极高:能生成超高清、细节丰富、语义一致的样本(如1024×1024的复杂场景图); 2. 多模态能力强:完美支持文本-图像、图像-图像等多模态生成,文本引导精度高; 3. 训练稳定:无对抗过程,只需最小化MSE损失,不易出现模式崩溃; 4. 可控性强:通过CFG、LoRA微调等技术,可精准控制生成样本的风格、细节。 |
1. 生成速度慢:需T步(如50100步)去噪,生成一张512×512图像需15秒(比GAN慢10~100倍); 2. 计算成本高:即使在 latent 空间,仍需较大显存(如生成1024×1024图像需8GB以上显存); 3. latent 空间不可解释:难以通过手动调整 latent 向量控制生成结果(需依赖文本或图像引导)。 |
适用场景:高保真多模态生成任务(如文本生成图像、图像超分、图像编辑、3D资产生成),或对生成质量有高要求的场景(如游戏美术、广告设计、影视特效)。
五、三大生成式模型对比:如何选择适合自己的模型?
为了帮助开发者快速选择模型,我们从“核心思想、生成质量、训练难度、计算成本”等6个关键维度,对VAE、GAN、Diffusion Model进行对比:
对比维度 | VAE(变分自编码器) | GAN(生成对抗网络) | Diffusion Model(扩散模型) |
---|---|---|---|
核心思想 | 概率化自编码器,学习 latent 分布的参数 | 生成器与判别器的零和博弈 | 逐步加噪-逐步去噪,逆转扩散过程 |
生成质量 | 低(模糊,细节少) | 高(高保真,细节丰富) | 极高(超高清,语义一致) |
样本多样性 | 高(latent 空间连续,支持插值) | 中(易出现模式崩溃) | 高(无模式崩溃,支持多模态) |
训练难度 | 低(无对抗,损失稳定) | 高(需平衡生成器与判别器,超参数敏感) | 中(损失稳定,但需调噪声调度表) |
计算成本 | 低(单前向传播,无多步过程) | 中(对抗训练,单步生成) | 高(多步去噪,需大显存) |
适用场景 | 低分辨率生成、数据增广、异常检测 | 单模态高保真生成(人脸、风格迁移) | 多模态高保真生成(文本→图像、图像编辑) |
代表应用 | MNIST生成、 latent 空间插值 | StyleGAN(人脸生成)、Pix2Pix(图像翻译) | Stable Diffusion(文本→图像)、MidJourney(创意生成) |
选择建议:
- 若需求是“快速生成低分辨率样本,或需要 latent 空间插值”→ 选VAE;
- 若需求是“单模态高保真生成,且对速度有要求”→ 选GAN(如WGAN-GP、StyleGAN);
- 若需求是“多模态生成(如文本→图像),或超高清样本生成”→ 选Diffusion Model(如Stable Diffusion)。
六、实战:用Stable Diffusion实现文本生成图像(附完整代码)
接下来,我们聚焦工业级实战——用Hugging Face的diffusers
库,实现Stable Diffusion的三大核心功能:文本生成图像(txt2img)、图像生成图像(img2img)、LoRA微调(小数据集定制模型)。
6.1 环境准备
1. 硬件要求
- 显存:至少4GB(生成512×512图像),推荐8GB以上(生成1024×1024图像);
- GPU:支持CUDA的NVIDIA显卡(推荐RTX 3060及以上),AMD显卡需用ROCm(兼容性较差)。
2. 软件安装
# 安装PyTorch(支持CUDA 11.8,根据显卡型号调整)
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
# 安装Diffusers库(Hugging Face官方Stable Diffusion库)
pip install diffusers==0.24.0 transformers==4.35.2 accelerate==0.24.1
# 安装其他依赖(图像处理、模型下载)
pip install pillow matplotlib requests
3. 模型下载
Stable Diffusion的预训练模型需从Hugging Face Hub下载,推荐使用runwayml/stable-diffusion-v1-5
(开源、稳定、效果好):
- 无需手动下载,
diffusers
库会自动下载并缓存到本地(默认路径:~/.cache/huggingface/diffusers
); - 若下载速度慢,可配置Hugging Face镜像(如
export HF_ENDPOINT=https://hf-mirror.com
)。
6.2 功能1:文本生成图像(txt2img)
文本生成图像是Stable Diffusion最核心的功能,输入文本描述(Prompt),输出对应图像。
完整代码
import torch
from diffusers import StableDiffusionPipeline
import matplotlib.pyplot as plt
from PIL import Image
# 1. 加载Stable Diffusion模型(指定GPU)
device = "cuda" if torch.cuda.is_available() else "cpu"
pipe = StableDiffusionPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5", # 预训练模型名称
torch_dtype=torch.float16, # 使用FP16精度,节省显存
safety_checker=None # 关闭安全检查(可选,避免过滤部分图像)
).to(device)
# 2. 配置生成参数
prompt = "A photo of a cute cat wearing a astronaut helmet, on the moon, stars in the sky, ultra-detailed, 8k resolution" # 正向Prompt(要生成的内容)
negative_prompt = "blurry, low resolution, ugly, deformed, watermark, text" # 反向Prompt(要避免的内容)
num_inference_steps = 50 # 去噪步数(越多越清晰,但越慢,推荐20~100)
guidance_scale = 7.5 # CFG Scale(文本引导强度,越大越贴合Prompt,推荐7~10)
height = 512 # 生成图像高度(推荐512/768/1024)
width = 512 # 生成图像宽度
num_images_per_prompt = 1 # 每次生成的图像数量
# 3. 生成图像
with torch.no_grad(): # 禁用梯度计算,节省显存
images = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
num_inference_steps=num_inference_steps,
guidance_scale=guidance_scale,
height=height,
width=width,
num_images_per_prompt=num_images_per_prompt
).images
# 4. 保存并显示图像
save_path = "stable_diffusion_txt2img.png"
images[0].save(save_path)
print(f"图像已保存到:{save_path}")
# 显示图像
plt.figure(figsize=(8, 8))
plt.imshow(images[0])
plt.axis("off")
plt.title("Text-to-Image Result\nPrompt: " + prompt[:50] + "...")
plt.show()
关键参数说明
- Prompt:文本描述需精准、详细,使用专业术语(如“ultra-detailed”“8k”“photorealistic”)提升生成质量;
- negative_prompt:避免生成“模糊、低分辨率、畸形”等不良图像,是提升质量的关键;
- num_inference_steps:50步足够生成清晰图像,超过100步后质量提升不明显,但时间翻倍;
- guidance_scale:7.5是平衡点,小于5会偏离Prompt,大于10会导致图像失真。
生成结果示例
输入Prompt:“A photo of a cute cat wearing a astronaut helmet, on the moon, stars in the sky, ultra-detailed, 8k resolution”
生成结果:一只戴着宇航员头盔的可爱猫咪,站在月球表面,背景是星空,细节丰富,画质清晰。
6.3 功能2:图像生成图像(img2img)
图像生成图像(Image-to-Image)是在已有图像的基础上,根据文本Prompt调整风格或内容(如“将照片转为油画”“给猫咪添加围巾”)。
完整代码
import torch
from diffusers import StableDiffusionImg2ImgPipeline
import matplotlib.pyplot as plt
from PIL import Image
# 1. 加载输入图像(可替换为自己的图像路径)
init_image_path = "input_cat.jpg" # 输入图像(如一张猫咪照片)
init_image = Image.open(init_image_path).convert("RGB")
init_image = init_image.resize((512, 512)) # 调整为512×512(与模型输入匹配)
# 2. 加载Stable Diffusion img2img模型
device = "cuda" if torch.cuda.is_available() else "cpu"
pipe = StableDiffusionImg2ImgPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5",
torch_dtype=torch.float16,
safety_checker=None
).to(device)
# 3. 配置生成参数
prompt = "The cat in the image is wearing a red scarf, oil painting style, vibrant colors, ultra-detailed" # 正向Prompt(在输入图像基础上添加围巾,转为油画风格)
negative_prompt = "blurry, low resolution, ugly, deformed, watermark"
num_inference_steps = 50
guidance_scale = 7.5
strength = 0.7 # 图像调整强度(0~1,越大越偏离原图,越小越接近原图,推荐0.5~0.8)
# 4. 生成图像
with torch.no_grad():
images = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
image=init_image,
num_inference_steps=num_inference_steps,
guidance_scale=guidance_scale,
strength=strength
).images
# 5. 保存并显示对比结果
save_path = "stable_diffusion_img2img.png"
images[0].save(save_path)
print(f"图像已保存到:{save_path}")
# 显示输入图像与生成图像对比
plt.figure(figsize=(12, 6))
# 输入图像
plt.subplot(1, 2, 1)
plt.imshow(init_image)
plt.axis("off")
plt.title("Input Image")
# 生成图像
plt.subplot(1, 2, 2)
plt.imshow(images[0])
plt.axis("off")
plt.title("Image-to-Image Result\nPrompt: " + prompt[:50] + "...")
plt.show()
关键参数说明
- strength:控制“原图保留程度”,0.7表示“保留30%原图特征,70%按Prompt生成”;
- init_image:输入图像需为RGB格式,分辨率建议与生成图像一致(如512×512),避免拉伸变形。
生成结果示例
输入图像:一张普通猫咪照片
生成结果:猫咪戴上了红色围巾,整体风格转为油画,色彩鲜艳,细节丰富,同时保留了猫咪的原始姿态。
6.4 功能3:LoRA微调(小数据集定制模型)
LoRA(Low-Rank Adaptation,低秩适配)是一种轻量级微调技术,只需少量数据(如10~100张图像),就能让Stable Diffusion生成特定风格或对象的图像(如“生成特定角色的动漫图”“生成特定画家的风格图”)。
1. 准备数据集
- 数据集要求:10~100张同一风格/对象的图像(如10张“皮卡丘”动漫图),分辨率建议512×512;
- 数据标注:每张图像需搭配Prompt(如“a photo of pikachu, anime style”),保存为CSV文件(格式:
image_path,prompt
)。
示例CSV文件(dataset.csv
):
image_path,prompt
pikachu/1.jpg,a photo of pikachu, anime style, cute, yellow fur
pikachu/2.jpg,a photo of pikachu, anime style, standing, holding a ball
pikachu/3.jpg,a photo of pikachu, anime style, sitting, grass background
...
2. 完整微调代码
import torch
import csv
import os
from diffusers import StableDiffusionPipeline, LoRAConfig, get_scheduler
from diffusers.training_utils import EMAModel
from diffusers.optimization import get_scheduler
from torch.utils.data import Dataset, DataLoader
from PIL import Image
import torchvision.transforms as transforms
# 1. 定义数据集类
class LoRADataset(Dataset):
def __init__(self, csv_path, image_dir, transform=None):
self.data = []
with open(csv_path, "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
image_path = os.path.join(image_dir, row["image_path"])
prompt = row["prompt"]
self.data.append((image_path, prompt))
self.transform = transform
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
image_path, prompt = self.data[idx]
image = Image.open(image_path).convert("RGB")
if self.transform:
image = self.transform(image)
return {"image": image, "prompt": prompt}
# 2. 配置参数
csv_path = "dataset.csv" # CSV文件路径
image_dir = "." # 图像文件夹路径
output_dir = "lora-pikachu" # LoRA模型保存路径
batch_size = 2 # 批次大小(根据显存调整,4GB显存用1~2)
num_train_epochs = 50 # 训练轮数(10~50,数据少则多轮)
learning_rate = 1e-4 # 学习率(推荐1e-4~1e-3)
lora_rank = 4 # LoRA秩(越小参数越少,推荐4~8)
lora_alpha = 8 # LoRA alpha(通常为rank的2倍)
image_size = 512 # 图像尺寸
# 3. 数据预处理
transform = transforms.Compose([
transforms.Resize((image_size, image_size)),
transforms.ToTensor(),
transforms.Normalize([0.5], [0.5]) # 归一化到[-1, 1](与模型输入匹配)
])
dataset = LoRADataset(csv_path, image_dir, transform)
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)
# 4. 加载基础模型与LoRA配置
device = "cuda" if torch.cuda.is_available() else "cpu"
# 加载Stable Diffusion基础模型
pipe = StableDiffusionPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5",
torch_dtype=torch.float16,
safety_checker=None
).to(device)
# 配置LoRA(只微调U-Net的Cross-Attention层)
lora_config = LoRAConfig(
r=lora_rank,
lora_alpha=lora_alpha,
target_modules=["to_q", "to_k", "to_v", "to_out.0"], # 目标微调层
lora_dropout=0.05,
bias="none",
task_type="TEXT_IMAGE_DIFFUSION"
)
# 为U-Net添加LoRA适配器
pipe.unet.add_adapter(lora_config)
# 冻结基础模型参数,只训练LoRA参数
for param in pipe.unet.parameters():
param.requires_grad = False
for param in pipe.unet.lora_adapters.parameters():
param.requires_grad = True
# 5. 配置优化器与学习率调度器
optimizer = torch.optim.AdamW(pipe.unet.lora_adapters.parameters(), lr=learning_rate)
lr_scheduler = get_scheduler(
"cosine",
optimizer=optimizer,
num_warmup_steps=0,
num_training_steps=len(dataloader) * num_train_epochs
)
# 6. 训练LoRA
pipe.unet.train()
for epoch in range(num_train_epochs):
epoch_loss = 0.0
for step, batch in enumerate(dataloader):
# 准备数据
images = batch["image"].to(device, dtype=torch.float16)
prompts = batch["prompt"]
# 编码文本
text_inputs = pipe.tokenizer(
prompts,
padding="max_length",
max_length=pipe.tokenizer.model_max_length,
truncation=True,
return_tensors="pt"
).to(device)
# 生成随机噪声与时间步
noise = torch.randn_like(images).to(device)
timesteps = torch.randint(0, pipe.scheduler.num_train_timesteps, (images.shape[0],), device=device).long()
# 前向扩散:生成带噪声的图像
noisy_images = pipe.scheduler.add_noise(images, noise, timesteps)
# 模型预测噪声
model_output = pipe.unet(noisy_images, timesteps, text_inputs.input_ids).sample
# 计算MSE损失(预测噪声与真实噪声的差异)
loss = torch.nn.functional.mse_loss(model_output, noise)
# 反向传播与参数更新
loss.backward()
optimizer.step()
lr_scheduler.step()
optimizer.zero_grad()
# 累计损失
epoch_loss += loss.item() * images.shape[0]
# 打印每轮损失
avg_loss = epoch_loss / len(dataset)
print(f"Epoch {epoch+1}/{num_train_epochs} | Average Loss: {avg_loss:.4f}")
# 7. 保存LoRA模型
pipe.unet.save_attn_procs(output_dir)
print(f"LoRA模型已保存到:{output_dir}")
# 8. 加载LoRA模型进行生成测试
pipe = StableDiffusionPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5",
torch_dtype=torch.float16,
safety_checker=None
).to(device)
# 加载LoRA模型
pipe.unet.load_attn_procs(output_dir)
# 生成测试图像
prompt = "a photo of pikachu, anime style, flying in the sky, clouds background, ultra-detailed"
negative_prompt = "blurry, low resolution, ugly, deformed"
with torch.no_grad():
image = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
num_inference_steps=50,
guidance_scale=7.5,
height=512,
width=512
).images[0]
# 保存测试图像
image.save("lora_test.png")
print("LoRA测试图像已保存到:lora_test.png")
plt.figure(figsize=(8, 8))
plt.imshow(image)
plt.axis("off")
plt.title("LoRA Fine-tuning Result\nPrompt: " + prompt[:50] + "...")
plt.show()
关键参数说明
- lora_rank:LoRA的核心参数,秩越小,模型参数越少(如rank=4时,LoRA模型仅几十MB),微调速度越快;
- num_train_epochs:小数据集(如10张图)需训练50轮以上,确保模型学习到目标风格/对象;
- batch_size:根据显存调整,4GB显存用1,8GB显存用2~4,避免显存溢出。
微调结果示例
微调后,输入Prompt:“a photo of pikachu, anime style, flying in the sky, clouds background”
生成结果:符合训练数据风格的皮卡丘,在空中飞行,背景是云朵,与训练集中的皮卡丘风格高度一致。
七、南木的学习路径建议:从入门到精通生成式模型
生成式模型涉及概率统计、深度学习、优化理论等多个领域,初学者容易陷入“原理难懂、代码跑不通”的困境。结合我的经验,推荐一条“循序渐进”的学习路径:
阶段1:基础铺垫(2~3周)
- 数学基础:复习概率统计(高斯分布、KL散度、期望)、线性代数(矩阵乘法、低秩分解)、微积分(梯度下降、链式法则)——无需深钻,能理解公式含义即可;
- 工具基础:掌握PyTorch核心操作(张量、模型定义、反向传播)、图像处理(PIL、OpenCV)、数据加载(Dataset、DataLoader);
- 前置知识:学习自编码器、CNN、Transformer的基础结构,理解“编码器-解码器”“注意力机制”的核心思想。
阶段2:核心原理(4~6周)
- 第一步:入门VAE:
- 实现简单VAE(如生成MNIST图像),理解“重参数化技巧”和“ELBO损失”;
- 可视化latent空间,观察插值生成效果,理解“概率生成”的意义;
- 第二步:深入GAN:
- 实现原始GAN(生成MNIST),观察训练不稳定问题;
- 实现WGAN-GP,对比原始GAN的改进效果,理解“Wasserstein距离”和“梯度惩罚”;
- 学习StyleGAN的“风格迁移”思想,尝试生成人脸图像;
- 第三步:精通Diffusion Model:
- 推导DDPM的前向/反向扩散公式,理解“噪声预测”的逻辑;
- 阅读Stable Diffusion论文,理解“latent diffusion”和“文本引导”的实现;
- 用
diffusers
库复现DDPM,对比与Stable Diffusion的差异。
阶段3:实战进阶(4~8周)
- 基础实战:
- 用Stable Diffusion实现txt2img、img2img、图像超分、图像修复;
- 学习Prompt工程,掌握“关键词组合”“权重调整”(如
(astronaut:1.2)
)提升生成质量;
- 进阶实战:
- 实现LoRA微调,定制特定风格/对象的模型(如生成自己的漫画形象);
- 学习ControlNet,实现“姿态控制”“深度控制”(如用骨架图生成对应姿势的人物);
- 尝试多模态生成(如文本生成视频、文本生成3D模型),使用开源库(如Pika、DreamFusion);
- 工程优化:
- 学习模型量化(如FP16/FP8量化)、模型蒸馏,降低显存占用;
- 实现批量生成、异步生成,提升生成效率;
- 部署Stable Diffusion到Web端(如用Gradio、Streamlit搭建交互界面)。
阶段4:前沿扩展(长期)
- 理论研究:
- 阅读生成式模型的最新论文(如Google的Imagen、Meta的Make-A-Video),跟踪技术趋势;
- 研究生成式模型的评估指标(如FID、CLIP Score、Human Evaluation),理解“生成质量”的量化标准;
- 跨领域应用:
- 探索生成式模型在工业界的应用(如游戏美术、广告设计、影视特效、生物医药);
- 结合大语言模型(如GPT-4),实现“文本理解→精细Prompt生成→图像生成”的端到端流程;
- 技术突破:
- 研究生成速度优化(如Fast Diffusion、LCM),实现实时生成;
- 探索生成式模型的可控性(如编辑生成图像的局部内容),解决“生成结果不可控”的痛点。
生成式模型的发展,是AI从“感知”走向“创造”的关键一步——从VAE的“概率探索”,到GAN的“对抗创新”,再到Diffusion Model的“精细生成”,每一次技术迭代都在拓宽“机器创意”的边界。
当前,Diffusion Model凭借“高生成质量+强多模态能力”,成为AIGC的主流技术,但GAN在“单模态快速生成”场景仍有不可替代的优势,VAE则在“低计算成本”场景发挥作用。未来,生成式模型的发展方向将是“更高质量、更快速度、更强可控性、更多模态融合”——比如实时生成4K视频、精准控制3D模型生成、实现文本-图像-视频-3D的端到端生成。
对于开发者而言,学习生成式模型不仅是掌握一项技术,更是把握AIGC时代的核心竞争力。
如果在学习过程中遇到问题,欢迎在评论区留言,我会定期回复。觉得有用的话,记得点赞+收藏+关注,后续我会分享更多生成式模型的实战干货
更多推荐
所有评论(0)