资讯动态

Stable Diffusion原理详解:CLIP、扩散模型与UNet全解析

发布时间:2026/10/26 20:27:56 来源:尧图企业网站定制
1. 为什么知其所以然比一键出图更重要我最早接触 Stable Diffusion 的时候和大多数人一样第一反应是找一个整合包装好然后在提示词框里输入仙女、珊瑚、光影特效点击生成。图出多了以后我发现同样的提示词换个模型表现完全不同同一个模型换个采样步数结果也可能翻天覆地。如果只把 Stable Diffusion 当成抽卡工具这些问题永远只能靠运气但如果绕到背后把 CLIP、扩散模型、UNet 这三块拼图拼起来一切都会变得有迹可循。这篇文章是我在看完四集精讲视频之后整理的完整学习笔记。四集内容其实不多但信息密度很大第一遍看很容易眼睛会了、脑子没会。我把四集拆成七个小节按自己的理解重新组织了一遍并把每部分的代码示例也跑通了算是一份看完就能照着复现的笔记。准备说在前面这篇文章不是纯论文解读也不是纯 GUI 操作教程。它更适合那些已经在用 Stable Diffusion 出图但对内部机制还比较模糊的玩家也适合刚入门的开发者想知道 diffusers 这类开源库在调用时到底发生了什么。整条主线只有一条一段文字是怎么一步步变成一张图的。沿着这条主线CLIP、扩散模型、UNet 各自负责哪个环节就都清楚了。1.1 我为什么用四集笔记来整理这套原理网上讲 Stable Diffusion 的文章非常多但大多数要么只讲某一部分概念要么直接教你怎么写提示词缺少一条完整的链路。四集精讲的好处在于从为什么需要文本编码器讲起到噪声如何被清除再到UNet 怎么处理信息最后落到可运行的代码逻辑是递进的。我整理笔记时没有照抄原稿而是自己做了一张流程卡片把每个环节的输入输出和关键参数都列出来了。这样即使隔了很久回头翻笔记也只需要看那一张卡片就能回忆起来。1.2 本文会讲清楚的两条主线第一条主线是训练阶段的分工CLIP 文本编码器把自然语言转换成向量扩散模型定义加噪-去噪的学习目标UNet 负责在每一步去噪中预测噪声最后通过 VAE 解码器把潜在表示还原成图像。第二条主线是推理阶段的流水线输入提示词 → 文本编码 → 随机噪声初始化 → UNet 逐步去噪 → VAE 解码 → 输出图片。这两条主线一旦清楚了你在界面上看到的每一个参数采样步数、CFG Scale、种子、分辨率就都有了明确的对应关系。2. 三大部分的整体串联CLIP、扩散过程与 UNet 的各自职责先来看一张服务与被服务的关系。很多人以为 Stable Diffusion 是一个端到端的大模型其实它更像一个组装车间四个模块分别处理自己的事。2.1 从输入到输出的数据流动如果只记一句话可以这样概括CLIP 负责把文字变成条件扩散过程负责定义从纯噪声到画面的演化规则UNet 负责在这个规则下实际执行去噪VAE 解码器负责把压缩空间的图像表示还原成像素图。具体的数据流向是这样的。用户输入提示词后会先经过一个分词器把句子切成一连串的 token再送到 CLIP 文本编码器里得到一组文本向量。这组向量不会直接变成图像而是作为一个条件注入到 UNet 中相当于告诉生成模型你往这个方向画。与此同时模型从随机噪声开始生成一张和最终图像同尺寸的初始噪声图。这个初始噪声在潜在空间里是一个带随机数的张量它经过 UNet 的每一轮去噪逐步暴露出清晰的轮廓、结构和细节。经过几十步迭代后最终得到的干净潜在表示被塞进 VAE 解码器就能还原成一张直观理解的 RGB 图片。2.2 各模块的分工对比我整理了一张简化的分工表方便快速对照模块输入输出核心作用典型瓶颈CLIP 文本编码器提示词 token 序列文本嵌入向量序列把文字语义转成模型能用的条件最大支持 77 个 token扩散调度器初始噪声 / 上一步结果逐步去噪后的潜在向量定义噪声强度随时间的变化规则采样步数影响速度与质量UNet 去噪网络噪声潜在向量 时间步 文本条件预测出的噪声学习图片长什么样从而去噪显存占用最大VAE 解码器干净潜在向量像素图像把压缩空间的表示还原成真实图片解码耗时短基本忽略这张表非常重要。尤其是UNet 负责预测噪声这件事很多新手第一次听到会困惑为什么要预测噪声而不是直接预测图像这个问题我放在第 5 节详细讲。这里先记住结论扩散模型的训练目标就是从随机噪声里反推加噪过程的逆步骤UNet 输出的其实是一个和输入同样尺寸的噪声图用它来修正当前潜在向量从而一步步逼近真实图像。2.3 四集笔记里最容易被忽略的一句话四集视频里有一句话我印象特别深Stable Diffusion 本质上是一个条件生成模型。条件二字是一切设计的前提。没有 CLIP 生成的条件UNet 面对同一个噪声输入就只能随机发挥有了条件生成的每一步都被校准到和提示词语义相符的方向上。那些换提示词就像换了一个世界一样的体验就是因为文本条件在昂首塑造生成结果。3. CLIP 双编码器架构细拆文本如何变成图像的方向盘CLIP 的全称是 Contrastive Language-Image Pre-training也就是对比语言-图像预训练。它最早是作为一种多模态模型被提出来的主要任务是让模型理解一段文本和一张图像是否匹配。在 Stable Diffusion 里我们只用到它的文本编码器部分但这部分决定了模型能听懂多少提示词。3.1 CLIP 到底训练了什么CLIP 的训练方式和传统分类任务完全不同。它不用人工标注的类别标签而是直接使用海量的图文对一张图片配一句描述文字。训练时模型把一张图编码成一个向量也把一段描述文字编码成一个向量然后计算这两个向量的相似度。目标是如果这张图和这段文字本来就是一对相似度要高如果它们不是一对相似度要低。这个目标是通过对比学习实现的。简单说模型会同时看一个批次里的多张图和多个句子找出哪些组合是正样本对哪些是负样本对然后不断调整编码器参数。训练结束后两个编码器——图像编码器和文本编码器——被推进同一个语义向量空间。在这个空间里一只橘猫坐在沙发上这句话的向量和一张真实橘猫坐在沙发上的图片向量会非常靠近。Stable Diffusion 在生成图片时正是希望文本向量能起到方向盘的作用。它先让文本编码器把用户提示词映射成一个向量序列然后在 UNet 每一步去噪时都用这个向量序列来引导告诉模型当前潜在表示应该更像猫而不是像狗。3.2 为什么这里的文本编码器直接决定了懂不懂话很多人测试不同模型时会发现同一个提示词在 SD 1.5、SD 2.1、SDXL 上的表现差异很大。除了 UNet 本身的改进之外文本编码器也是一个重要变量。SD 1.x 系列使用的是 CLIP ViT-L/14 的文本分支它的理解能力上限决定了提示词表达的天花板。文本编码器的工作流程大致是先通过 BPE 分词器把提示词拆成 token 序列每个 token 对应一个嵌入向量然后经过一层层的 Transformer 编码器最终输出一组 hidden states。这组 hidden states 就被当作文本条件送入 UNet 的交叉注意力层。我自己的实测感受是SD 1.5 对比较复杂的长句容易丢细节比如你写蓝色眼睛的女孩穿着红色连衣裙在雨中等候五个关键词可能只能突出两三个而 SDXL 使用了两套文本编码器组合理解长句的能力明显更强。这和文本编码器的上下文长度、参数规模直接相关。所以不要小看 CLIP 这部分它决定了提示词里有多少信息能真正进入去噪过程。3.3 77 token 限制与 CLIP limit 的坑网上搜CLIP limit会看到大量相关讨论几乎所有 SD 老玩家都遇到过提示词写得太长后半段被截断生成结果完全没体现后面的内容。这是怎么回事因为 SD 1.x 的 CLIP 文本编码器在训练时只支持 77 个 token 的上下文窗口。一旦超过 77 个 token超出部分要么被直接截断要么只参与计算一部分。很多人在 WebUI 里堆了几百个词前面一段是主要角色后面全是极其精细的细节、让人惊叹的光影结果发现模型实际只用了前 77 个 token后面的全部被忽略。我用一个简单例子说明提示词a cat, a dog, a bird, a fish只有 8 个 token但如果你在后面继续加几百个修饰词超过 77 个 token 之后的内容确实会被丢掉。所以在实操里重要的主体描述一定要放在提示词最前面质量 tag 可以往后放反正如果超过窗口也未必能起作用。提示如果你用 ComfyUI 里常见的 CLIP Text Encode 节点可以在 KSampler 的配置里看到clip_skip这一类参数。SD 1.x 常用clip_skip2跳过最后一层文本编码输出能改善部分画面偏灰的问题。这也是属于 CLIP 的微观调校。3.4 一个值得尝试的小实验如果你手头有 SD WebUI 或者 ComfyUI可以做一个实验把clip_skip分别设为 1 和 2固定种子、提示词和采样参数对比两次输出。你会发现画面的对比度、细节锐度和风格倾向会有细微变化。这个实验不需要花很多时间但对理解文本编码器的哪一层被使用了非常有帮助。CLIP 最后一层往往更偏向全局语义而倒数第二层可能保留更多细粒度信息跳过最后一层有时反而让画面更符合提示词。4. 扩散模型的数学直觉前向加噪与反向去噪扩散模型听起来玄核心思想其实一句话就能讲明白给图像不断加噪声直到变成纯噪声然后训练一个神经网络学会把噪声一步步去掉还原出图像。Stable Diffusion 用的扩散模型不是最原始的版本而是潜在扩散模型但底层原理一脉相承。4.1 前向扩散过程一张图的信息被逐步掩盖前向过程就是你坐在那里往一张清晰的图片上叠加高斯噪声。每叠一步图片就模糊一点。加噪声的强度由一个时间步 t控制t 越大噪声越强当 t 达到最大值时图已经面目全非和真正的随机高斯噪声没什么区别。数学上这个加噪过程通常写成下面的形式x_t sqrt(alpha_bar_t) * x_0 sqrt(1 - alpha_bar_t) * epsilon其中 x_0 是原始图像epsilon 是从标准高斯分布中采样的噪声alpha_bar_t 是一个随着 t 增大而递减的系数。当 t 接近 0 时sqrt(alpha_bar_t) 接近 1所以 x_t 几乎是原始图像当 t 很大时sqrt(alpha_bar_t) 接近 0所以 x_t 几乎全是噪声。这个公式的意义在于它不需要真正一步一步去加噪声而是可以直接从 x_0 一步算出任意 t 时刻的加噪结果。训练扩散模型时我们随机抽一个 t随机生成一个噪声 epsilon然后用这个公式得到 x_t再让神经网络去预测当初的噪声 epsilon。整个过程既简单又高效。4.2 反向去噪过程让模型学会擦掉噪声反向去噪是扩散模型的推理阶段。我们想要的效果是从一张纯噪声开始一步步经过 UNet 的预测和修正最终得到接近真实分布的图像。在 DDPM 原始论文中反向过程的单步更新公式大致是x_{t-1} (1 / sqrt(alpha_t)) * (x_t - (1 - alpha_t) / sqrt(1 - alpha_bar_t) * eps_theta) sigma_t * z这个公式看着吓人拆开理解就不难eps_theta是 UNet 对当前噪声图中所含噪声的预测x_t减去噪声项之后得到一个更干净一点的潜在表示最后再加上一个随机扰动sigma_t * z来保证生成多样性。换句话说每一步去噪都不是直接把噪声完全清零而是走一小步。从 t T 开始每一轮 UNet 都做三件事看一眼当前带噪的潜在向量结合当前时间步 t再结合文本条件然后输出一个预测噪声用这个预测噪声计算下一步的潜在向量。这样重复 20 到 50 次就完成了从噪声到图像的转变。4.3 潜在空间扩散Stable Diffusion 名字里的潜在二字传统扩散模型直接操作像素空间也就是在 512×512×3 的 RGB 图像上做加噪去噪。这个做法的计算量非常大因为每个像素都是一个维度一张图就是几十万个维度在一张消费级显卡上跑一次生成要很慢。Stable Diffusion 采用的潜在扩散模型不一样。它先训练一个 VAE 自编码器把图像压缩到一个更小的潜在空间里比如 512×512 的图可能被压缩成 64×64 或 128×128 的潜在表示。扩散过程就发生在这个低维潜在空间里而不是直接在像素空间里。这相当于把在几十万维空间里做扩散降为在几千维空间里做扩散计算量下降非常明显。这也是为什么 Stable Diffusion 能在消费级 GPU 上跑而很多早期的 Diffusion 模型却很难实用。代价是潜在空间的压缩会让一些非常细微的结构信息丢失比如手部细节。这一部分与后面要讲的手部修复问题直接相关。提示你可以把 VAE 潜在空间理解为图像的浓缩版糖浆。浓缩之后大方向构图、主体、材质都被保留但有些细小颗粒手指、发丝可能会被压缩得面目全非。UNet 在潜在空间里预测噪声自然也就很难把每个手指的关节都维护得严丝合缝。5. UNet 架构去噪主角以及文本条件如何注入如果说 CLIP 是方向盘扩散过程是道路规划那 UNet 就是实际开车的司机。它是整个 Stable Diffusion 里参数最多的模块也是每一步迭代中最消耗显存的部分。5.1 UNet 的骨架下采样、上采样与跳跃连接UNet 最早是为图像分割提出来的形状像字母 U因此得名。它由两部分组成左侧的编码器负责逐步下采样把特征图缩小通道数扩大从而提取越来越抽象的语义特征右侧的解码器负责逐步上采样把特征图恢复到原始尺寸并结合左侧对应层的特征进行重建。关键在于跳跃连接。下采样时每一层的特征图不仅向下传递还会抄近路直接跳到右侧对应的上采样层和上采样结果拼接在一起。这样右层既能利用低层的高分辨率细节也能利用高层的抽象语义。对去噪任务来说这种做法非常合适既要保持构图的大结构也要保留边缘和纹理等局部细节。在 Stable Diffusion 中UNet 的输入通常是带噪声的潜在向量、时间步 t 的嵌入以及文本条件。它输出的是预测噪声本质上也是一个和输入潜在向量同样尺寸的张量。5.2 时间步条件与文本条件CrossAttention 是关键UNet 不是普通的分割网络它额外增加了两种条件输入。第一种是时间步 t。模型通过一个正弦位置编码把 t 映射成向量再通过几个全连接层变成时间嵌入注入到 UNet 的每个残差块中。这样模型在 t 比较大的阶段主要处理高噪声在 t 比较小的阶段主要恢复细节不同阶段可以用不同的策略。第二种是文本条件。文本嵌入序列并不是简单地拼接到潜在向量后面而是通过交叉注意力机制进入 UNet。交叉注意力的公式和标准注意力一样但有一个关键区别查询 Query 来自图像特征键 Key 和值 Value 来自文本嵌入。这样每个图像位置都会去查找文本中最相关的部分相当于告诉模型这片区域要表现的是词 A 的含义那个区域要受词 B 的影响。我画过一条很形象的类比把整个生成过程想象成开会。每次开会图像特征负责提问文本条件负责回答问题最后的决议就是融合后的新特征。提问内容不同、回答内容不同决议自然不同。这也是为什么一只坐着的猫和一只奔跑的猫在同样的噪声初始化下会引导出完全不同的画面。5.3 为什么预测噪声而不是直接预测图像初学者最容易在这个问题上卡住。既然最终目标是图像为什么不直接让 UNet 从噪声一步到位预测出清晰图像关键在于学习难度。直接预测图像相当于让网络一步跨越几十步的复杂映射很难优化而且生成的图像容易模糊。预测噪声的本质是学习这一步该去除多少噪声这是一步一步的增量学习每一步的预测目标都很明确。训练时我们已知 x_t 是通过公式 x_t sqrt(alpha_bar_t) * x_0 sqrt(1 - alpha_bar_t) * epsilon 得到的最终的噪声 epsilon 是已知的网络只需要学会从 x_t 中反推 epsilon任务简单得多。在采样时每次得到预测噪声 epsilon_theta 后再通过调度器的更新公式推算出 x_{t-1}。所以 UNet 不是直接输出图像而是输出一张噪声地图指挥调度器如何修改当前潜在向量。整个过程像修复旧照片每次只擦掉一层污渍擦三四次就能看清大轮廓再擦十几次就能看到完整细节。6. 一块 GPU 也能跑的文生图实战diffusers 库从零出图理论部分铺完了接下来进入代码实战。我用的环境是 Python diffusers 库这也是目前最主流的开源推理方案。只要显卡显存不低于 6GB跑 SD 1.5 一般没有太大压力如果只有 CPU也能跑只是速度慢很多一张 512×512 的图可能需要几分钟到十几分钟。6.1 环境准备与依赖安装建议创建一个干净的环境然后安装以下依赖pip install diffusers transformers accelerate torch torchvision pillow如果你有 NVIDIA 显卡确保安装了对应版本的 CUDA 和 PyTorch没有显卡的话PyTorch 会走 CPU 路线也可以跑但体验会差不少。我建议先用一个现成的模型权重文件夹或用社区里常见的模型仓库把模型下载到本地这样后面代码里的from_pretrained路径就能直接指向本地路径。提示第一次加载模型需要下载权重时间会比较长。建议直接在代码里设置本地路径。文件名不要包含中文和空格避免出现奇怪的路径问题。6.2 跑通 StableDiffusionPipeline最简三行出图diffusers 把整个流程封装在StableDiffusionPipeline里用起来非常简洁。下面是一个最基础的例子from diffusers import StableDiffusionPipeline, DPMSolverMultistepScheduler import torch pipe StableDiffusionPipeline.from_pretrained( 你的本地模型路径, torch_dtypetorch.float16, safety_checkerNone, ) pipe.scheduler DPMSolverMultistepScheduler.from_config(pipe.scheduler.config) pipe pipe.to(cuda) prompt a cute corgi floating in a cup of coffee, masterpiece, best quality image pipe( promptprompt, negative_promptlowres, bad anatomy, worst quality, num_inference_steps25, guidance_scale7.5, seed42, ).images[0] image.save(output.png)这段代码涵盖了文生图的完整流程文本编码、随机初始化噪声、UNet 迭代去噪、VAE 解码。seed42是 diffusers 里常见的固定随机种子方式可以保证同一提示词在同一模型下生成结果可复现。如果你发现输出的图片完全随机可以检查一下是否手动设置了随机种子。DPMSolverMultistepScheduler是比原始 DDPM 调度器快很多的采样器25 步的效果通常能追平之前的 50 步是当前最常用的一套配置。6.3 自己拆开采样循环看清 UNet 每次在干嘛如果你只是想出图用pipe()就够了但如果你想真正理解UNet 到底在哪一步被调用、CFG 是怎么工作的建议把采样循环拆开手动跑一遍。diffusers 提供了StableDiffusionPipeline内部组件可以像下面这样逐个调用import torch from diffusers import StableDiffusionPipeline, DPMSolverMultistepScheduler pipe StableDiffusionPipeline.from_pretrained( 你的本地模型路径, torch_dtypetorch.float16, safety_checkerNone, ) pipe.scheduler DPMSolverMultistepScheduler.from_config(pipe.scheduler.config) pipe pipe.to(cuda) prompt a cute corgi floating in a cup of coffee negative_prompt lowres, bad anatomy prompt_embeds pipe.encode_prompt(prompt, negative_prompt, do_classifier_free_guidanceTrue) # prompt_embeds 返回 (text_embeds, negative_text_embeds) 或合并后的序列视版本而定 latents torch.randn( (1, pipe.unet.config.in_channels, 64, 64), devicecuda, dtypetorch.float16, ) latents latents * pipe.scheduler.init_noise_sigma pipe.scheduler.set_timesteps(num_inference_steps25) for t in pipe.scheduler.timesteps: latent_model_input torch.cat([latents] * 2) # 无条件与有条件各一份 latent_model_input pipe.scheduler.scale_model_input(latent_model_input, t) with torch.no_grad(): noise_pred pipe.unet( latent_model_input, t, encoder_hidden_statesprompt_embeds, ).sample uncond_pred, cond_pred noise_pred.chunk(2) # CFG 公式最终预测 uncond guidance_scale * (cond - uncond) noise_pred uncond_pred 7.5 * (cond_pred - uncond_pred) latents pipe.scheduler.step(noise_pred, t, latents).prev_sample with torch.no_grad(): image pipe.vae.decode(latents / pipe.vae.config.scaling_factor, return_dictFalse)[0] image (image / 2 0.5).clamp(0, 1) image image.permute(0, 2, 3, 1).float().cpu().numpy()这段代码里最关键的部分是do_classifier_free_guidanceTrue时为了做 CFG需要把输入复制成两份一份用于无条件预测一份用于带条件预测。最终噪声预测是两者的加权融合noise_pred uncond_pred guidance_scale * (cond_pred - uncond_pred)guidance_scale越大模型越听话画面越贴合提示词但多样性会降低超过一定数值还可能过饱和、出现伪影。这也是手调参数时最需要关注的旋钮。手动拆开采样循环还有一个好处你可以清楚地看到 UNet 每步的输入是 latents、时间步 t、文本嵌入输出是 noise_pred。你会真切体会到第 5 节说的UNet 在预测噪声而不是在生成图像。6.4 输出质量相关的几个调参位置我在实测过程中总结了一套比较稳的基准参数适合 SD 1.5 模型参数推荐范围说明采样步数20 - 30步数过少容易粗糙步数过多收益递减guidance_scale5 - 8数值越大越贴近提示词但过高会糊分辨率512×512 或 768×768超出模型训练分辨率容易重复构图或结构崩坏种子固定或不固定固定种子便于复现不固定更利于抽卡CFG 搭配建议同时设置负面提示词负面提示词能显著减少画质崩坏如果对自己的显卡显存没有把握可以把torch_dtype设置为torch.float16并使用pipe.enable_attention_slicing()降低显存占用。有些集成包已经自动做了这些优化但自己跑的时候别忘了。7. 提示词与手部修复实操中最常踩的几个坑最后一部分聊聊实操里的高频问题。我相信几乎每个 SD 玩家都被手指崩坏折磨过。为什么 AI 绘画手部修复难题这么常见网上甚至有人统计SD 1.5 生成的人物出图手部完全正确的比例很低。这不是模型的道德问题背后有清晰的技术原因。7.1 手部崩坏的根源并不是模型看不懂手手部崩坏的根本原因有三个。第一训练数据里手部区域占图像的比例很小画面里大量的信号来自脸、身体和背景模型会重点学这些高频信息第二手部的结构复杂、自由度极高手指之间的重叠、弯曲、遮挡难以用简单的特征表达第三潜在空间扩散压缩了图像信息精细的手部结构在压缩和还原过程中容易丢失扩散模型难以准确恢复。很多新手试图通过在手部区域拼命堆提示词来解决比如加perfect hands, eight fingers, beautiful fingers实际上作用有限。原因在于 CLIP 文本编码器只能把提示词映射成语义向量它不能精准地告诉 UNet 每个像素里的手指关节该怎么旋转。所以行业内更常用的其实是修复流程而不是提示词魔法。7.2 修复手部的三招组合拳我实测下来比较有效的方案按照从简单到复杂排序可以归纳为三招第一招负面提示词与负面嵌入。在负面提示词里写入bad anatomy, bad hands, extra fingers, missing fingers, distorted fingers等标签能在一定程度上降低手部出错概率。如果模型支持负面嵌入negative embedding还可以加载专门训练过的负面嵌入文件比单纯的负面提示词更稳定。第二招局部重绘。先在 WebUI 或 ComfyUI 里用修复模式或蒙版工具把崩坏的手部区域涂掉然后只对该区域进行 inpaint 重绘。关键技巧是重绘时选择的区域不要太小最好把整个手腕和部分前臂一起框进去给模型足够的上下文来决定手指的位置和朝向另外把重绘幅度denoising strength控制在 0.4 到 0.6 之间既保留周围风格又能重置手部结构。第三招分步优化。先生成一张构图满意的图再用局部重绘或 imagedetail 类扩展单独把人物手臂部分裁剪出来放大大去噪修复细节后回贴原图。这一招更适合有明确构图需求、又不希望整体重抽的情况。我自己实践后的感受是指望删掉手这个角色来避坑是不行的因为构图需要手合理安排流程才是关键。先靠负面提示词降低概率再靠局部修复清理剩余问题基本能应对 80% 的手部事故。7.3 提示词工程从魔法单词到结构化指令用过一段 SD 后你会发现提示词不是写得多就有用而是要按结构化方式组织。我习惯把正面提示词拆成四段主体描述、环境背景、风格修饰、质量标签。主体描述a young woman with long silver hair, wearing a black leather jacket 环境背景standing in a rainy cyberpunk street, neon lights reflecting on wet asphalt 风格修饰cinematic lighting, detailed face, intricate details 质量标签masterpiece, best quality, ultra detailed, 8k负面提示词我通常会写得稍微宽一些但不要写满 77 个 token因为负面提示词也会占用文本编码窗口lowres, bad anatomy, bad hands, missing fingers, extra digits, blurry, jpeg artifacts, watermark, oversaturated, deformed很多人忽略了一个点提示词里的逗号不是分隔符而是 token 序列的自然分隔。模型不会严格按照逗号来组织语义相邻 token 的组合可能会产生意外联想。所以不要写太长的短语堆叠尽量用简短的词块让 CLIP 能更准确地捕捉每个概念。7.4 种子、CFG 与采样步数三个影响稳定性与随机性的旋钮最后聊聊参数背后的逻辑。种子决定了初始噪声的样子。固定种子后同一个提示词、同一个模型、同一个采样配置会得到几乎相同的构图。如果你的提示词没变但生成结果一直在漂先检查是不是没固定种子。CFG Scale 控制的是无条件预测和条件预测的差值权重。数值调大模型会更迎合提示词但可能丢失自然多样性数值过小生成结果容易偏抽象和提示词脱节。我看到很多新人在 12 以上乱拉结果画质反而下降。我通常建议从 7 起步微调范围控制在 5-9。采样步数也不是越多越好。对 DPMSolver 这种高阶调度器来说25 步和 30 步的差距已经很小但 50 步会让单张图耗时明显上升。如果你追求效率推荐 20-25 步如果画面出现明显楼梯效应或条纹再适当增加到 30 步左右。7.5 一点个人小结跑图这件事说到底是一个控制变量的过程。固定种子、固定模型、固定负面提示词然后单独调整一个参数观察变化记录结果。这样做三五次你就能摸清某个模型在哪些提示词、哪些参数下表现最好。很多看似困难的手部修复、风格统一问题本质上都是可以通过流程拆解来缓解的而不是完全依赖运气。我在整理完这套笔记后的最大体会是Stable Diffusion 的原理并不复杂但各个组件之间的配合非常有讲究。CLIP 负责理解语义扩散过程负责定义演化路径UNet 负责执行去噪VAE 负责最终还原。这四个模块串起来的链条就是整条文生图的完整链路。只要你愿意顺着这条链路走一遍源码、跑一次代码实验很多界面上的玄学参数都会变成有逻辑可推导的选择。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑