基本概念
参考视频https://www.bilibili.com/video/BV1re4y1m7gb/?spm_id_from=333.337.search-card.all.click&vd_source=f04f16dd6fd058b8328c67a3e064abd5
生成模型其实是主要是依赖概率分布,对输入特征的概率密度函数建模
隐空间(latent space)/隐变量 (hidden vairables)
用a估计c,用c估计b,达到a估计b的目的,c是隐变量
就是embedding, 得到的结果是可以插值的一系列特征,如椅子被压缩的2d向量是[0.4,0.5],桌子是[0.6,0.75],如果要在潜在空间上进行插值,需要对椅子集群和办公桌集群之间的latent space中的点进行采样,采样后的点输入模型解码器,得到的图像就是椅子和桌子之间的变体
基本结构
类似于自编码器auto encoder,encoder:高纬输入编码成低维的隐变量从而强迫神经网络学习最有信息量的特征,decoder:把隐藏层的隐变量,还原到初始维度,最好能还原到和原始数据几乎相同
在生成模型中,encoder来解决概率密度估计问题,对生成的概率分布进行采样,得到隐变量,在把隐变量输入decoder来得到近似真实样本
可以把diffusion想象成去噪自编码器。去噪自编码器结合正则化思想,是在传统自动编码器的基础上,通过向输入中注入噪声,然后利用含噪声的样本去重构不含噪声的输入。模型定义了一个马尔可夫链,用于在扩散步骤中缓慢地向数据添加随机噪声,然后通过学习逆转扩散过程从噪声中构建所需的数据样本。引入的噪声导致了信息的衰减,再通过去噪尝试还原原始数据,这样的多次迭代
能够使模型在给定噪声输入的情况下学习生成新图像。
GAN
之前速通过,见博文:GAN 用于图像增强_gan进行图像增强-CSDN博客
VAE(Variational Autoencoder)
VAE通过变分推断与重参数化技巧,为生成模型提供了概率框架。尽管生成质量不及GAN,但其稳定训练和隐空间解释性优势明显。后续改进模型(如VQ-VAE、NVAE)通过结构优化显著提升了生成能力。
变分下界(ELBO)
通过最大化证据下界近似数据对数似然。
采样x和隐变量z之间的关系
vae缩小Z隐变量的取值空间,通过变分推断求后验概率分布,qzx推断pzx
重参数化技巧
使梯度可通过随机隐变量传播,解决采样不可导问题
隐空间正则化
强制隐变量分布接近标准正态分布(KL散度约束)
vae会过拟合,概率分布是采样出来的,而非通过生成器encoder计算出来的,所以采样变量z里面有噪声,尽可能减小方差,如果方差为0那就是auto encoder,过拟合
优化思路
1.encoder decoder拆分
2. 引入噪声覆盖失真的空白编码区,输入多样性↑,输入鲁棒性↑ 原先离散编码点→整个连续的编码空间
避免过拟合:训练加入正则化
正则化:规范隐空间的组织
采样隐变量
decoder训练效果不好的时候降低噪声,过拟合了增加噪声
训练数据
无标注数据
图像:MNIST、CIFAR-10、CelebA等。非图像数据:文本、音频、分子结构等。
预处理
图像归一化到[0,1]或[-1,1]。文本需转换为词嵌入或序列编码
模型结构
训练过程
1.前向过程:
编码器输出q(z|x)的参数μ,σ。
重参数化采样Z。
解码器输出p(xz)的参数。
2.损失计算:
重构损失:如交叉熵(二分类数据)或MSE(连续数据)
KL散度:KL(q(z|x)‖ N(0,I))
总损失:L=重构损失+β*KL散度(β-VAE变体)
3.反向传播:
通过梯度下降同时优化编码器和解码器。
4.生成新样本
从N(0,1)采样z,输入解码器生成x^。
vae vs gan
改进方法
B-VAE:调整KL项权重(β>1)以提升解耦表示。
·VQ-VAE:引入矢量量化层离散化隐空间。
CVAE:条件VAE,通过额外信息(如类别)控制生成。
·NVAE:层级化隐变量与深度神经网络提升生成质量。
Pros&Cons
代码
import torch
import torch.nn as nn
import torch.nn.functional as Fclass Encoder(nn.Module):def __init__(self, input_dim, hidden_dim, latent_dim):super().__init__()self.fc1 = nn.Linear(input_dim, hidden_dim)self.fc_mu = nn.Linear(hidden_dim, latent_dim)self.fc_logvar = nn.Linear(hidden_dim, latent_dim)def forward(self, x):h = F.relu(self.fc1(x))mu = self.fc_mu(h)logvar = self.fc_logvar(h)return mu, logvarclass Decoder(nn.Module):def __init__(self, latent_dim, hidden_dim, output_dim):super().__init__()self.fc1 = nn.Linear(latent_dim, hidden_dim)self.fc2 = nn.Linear(hidden_dim, output_dim)def forward(self, z):h = F.relu(self.fc1(z))recon = torch.sigmoid(self.fc2(h))return reconclass VAE(nn.Module):def __init__(self, input_dim=784, hidden_dim=400, latent_dim=20):super().__init__()self.encoder = Encoder(input_dim, hidden_dim, latent_dim)self.decoder = Decoder(latent_dim, hidden_dim, input_dim)def reparameterize(self, mu, logvar):std = torch.exp(0.5 * logvar)eps = torch.randn_like(std)return mu + eps * stddef forward(self, x):mu, logvar = self.encoder(x.view(-1, 784))z = self.reparameterize(mu, logvar)recon_x = self.decoder(z)return recon_x, mu, logvar# 训练函数
def train(model, dataloader, optimizer, device):model.train()train_loss = 0for batch_idx, (data, _) in enumerate(dataloader):data = data.to(device)optimizer.zero_grad()recon_batch, mu, logvar = model(data)# 计算重构损失和KL散度BCE = F.binary_cross_entropy(recon_batch, data.view(-1, 784), reduction='sum')KLD = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp())loss = BCE + KLDloss.backward()train_loss += loss.item()optimizer.step()return train_loss / len(dataloader.dataset)# 示例调用
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
vae = VAE().to(device)
optimizer = torch.optim.Adam(vae.parameters(), lr=1e-3)# 训练循环
for epoch in range(10):loss = train(vae, train_loader, optimizer, device)print(f'Epoch {epoch}, Loss: {loss:.2f}')# 生成新样本
with torch.no_grad():z = torch.randn(64, 20).to(device)samples = vae.decoder(z).view(64, 1, 28, 28)
Diffusion
生成像GAN的generator一样简单,模型结构跟vae一样精细
https://www.zhihu.com/question/536012286/answer/2588275344
前向过程(加噪)(Forward / Diffusion Process)
数据分布→标准高斯
从真实数据(如图像)逐步加入高斯噪声,最后变成纯高斯分布(白噪声)。
过程是已知的、固定的、高斯的,定义成一系列概率转移
重参数化Reparametrizatio
逆向过程(去噪)(Reverse / Generation Process)
高斯噪声 → 数据
从高斯噪声一步步“去噪”回来,得到真实数据。
形式上类似高斯,但条件分布是未知的,我们要去学习它
因为逆过程从高斯分布出发(采样超容易),并且每一步都只是高斯采样 + 神经网络预测,整个生成过程连续、可控、可调。前向过程“逐渐加噪”,逆过程就“逐渐去噪”,变化都非常平滑。这种细粒度的步骤其实降低了建模难度,比一次性生成图像(如GAN)要“温和”很多。
训练目标
SDXL
base 文生图,refiner,图生图
VAE:细节优化
FLUX
效果也很nb
Kolors
UI
WebUI
ComfyUI:RunComfy
Controlnet
reference
id adapter
风格训练:
Stable Diffusion
编码 (Encoding)
将原始图像映射到一个低维的潜在空间(latent space),以便更高效地进行建模。
如果是文本,则用 CLIP 或类似的文本编码器转换为语义向量。
c=CLIP Text Encoder(text)
如果是图像,通常使用如 VAE(变分自编码器)的 encoder 模块提取特征;
VAE将图像编码到潜在空间:z =VAE Encoder(x)
扩散(Diffusion)
-
过程:
-
正向过程:在潜空间中逐步添加高斯噪声,模拟图像被破坏。q(zt|zt-1)
-
反向过程:使用神经网络一步步学习如何从纯噪声还原出原始潜在表示。∈θ(zt,t,c)
-
-
模型:使用 UNet 架构 的扩散模型,接受噪声图、时间步(timestep)、和文本条件向量作为输入。
-
共识:UNet 是目前最主流的扩散预测网络,支持跨尺度的特征提取和条件控制,效果好、可控性强。
调度器:常用如 DDIM 或 PNDM 等采样算法来加速反向过程。
解码(Decoding)
-
过程:将去噪后的潜在表示Z0重新映射回高分辨率的图像空间。x= VAE_Decoder(z0)
-
模型:使用与编码器配套的 VAE decoder。
-
共识:VAE decoder 是一个轻量、稳定的图像重建工具,可以恢复细节,提升图像清晰度。
文本引导的 cross-attention 机制
Pros&Cons
from diffusers import StableDiffusionPipeline
import torchmodel_id = "runwayml/stable-diffusion-v1-5"
pipe = StableDiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.float16)
pipe = pipe.to("cuda")prompt = "A futuristic cityscape at sunset"
image = pipe(prompt).images[0]
image.save("output.png")