简介:这份PDF文档围绕Stable Diffusion的安装与使用展开,面向希望入门人工智能绘画的开发者、设计爱好者以及具备一定Python基础的学习者,帮助其理清从环境准备到图像生成的整体脉络。文档共1个PDF文件,约814KB,以单文件形式组织,重点模块相对清晰,篇幅集中、便于随查随看,内容涵盖Python 3.7以上环境、PyTorch依赖、虚拟环境、CompVis代码库与预训练模型获取等关键环节,并对文生图命令、--prompt与--steps等参数调节、图像优化及GPU资源需求作出说明。已有945人学习,适合作为Stable Diffusion初学阶段的配置参考与概念梳理材料。读者可从中获得安装路径、依赖关系、模型获取渠道、运行入口和参数影响等方面的系统认识,也能据此判断本地硬件是否满足生成需求,减少因版本、依赖或资源不足带来的试错成本,为后续艺术创作与实验探索打下基础。
1. 文本如何变成像素:扩散模型真正做的事
一段文字进去,一张图出来。很多人第一次跑txt2img.py时会觉得这中间有个黑匣子:提示词只写了「一只飞翔的龙」,模型凭什么知道龙该有几片鳞、翅膀该朝哪边?
反直觉的结论是:模型根本没在「画」图。它做的事只有一件——从一团纯随机噪声出发,反复预测并减去噪声,几十步之后,噪声退干净,剩下的就是图。稳定扩散(Stable Diffusion)这类人工智能绘画软件之所以能跑在消费级显卡上,关键在于它不在像素空间里做这件事,而是把图像先压进一个维度低得多的潜空间,在那里完成去噪,最后再解码回像素。这条「编码—去噪—解码」的链路,决定了你安装时的每一个依赖、命令行里的每一个参数、以及显存为什么会爆。
搞懂这条链路,后面那些环境配置、虚拟环境、--plms、--steps才不是照抄的命令,而是有因果关系的选择。
2. 潜空间去噪:为什么压缩这一步决定了显存和速度
2.1 像素空间去噪的成本账
假设直接在 512×512 的 RGB 图上做扩散。张量形状是 3×512×512,接近 78 万个数值。U-Net 每一层都要在这上面做卷积和注意力,注意力层的计算量随空间位置数量呈平方增长——512×512 有 26 万个位置,两两之间的关系矩阵根本放不下。这是早期像素级扩散模型只能在大型集群上跑的直接原因。
潜空间方案把问题换了个尺度。一个自编码器(VAE)先把 512×512×3 的图像压成 64×64×4 的潜表示,位置数从 26 万降到 4096,缩了 64 倍。去噪全程都在这个 64×64×4 的小张量上进行,注意力矩阵的规模随之落到可接受范围。生成结束后再用 VAE 解码器还原成 512×512。
这里有个容易被忽略的取舍:VAE 是有损压缩,它能还原大体结构、色彩和纹理,但极细的文字、精确的对称图形容易糊。所以早期模型画手、画文字经常翻车,不是 U-Net 不努力,是潜空间里根本没保留那么多高频细节。
常见的实现思路是,训练时冻结 VAE,只训 U-Net 和文本编码器。这样潜空间的「坐标系」是固定的,U-Net 学的只是如何在这个坐标系里把噪声拨回真实图像的分布。
2.2 文本条件是怎么注入的
文本侧由 CLIP 文本编码器处理。提示词被 tokenize 成定长序列(通常是 77 个 token),过一遍 Transformer,得到每个 token 的向量表示。这些向量不是拼到图像张量上,而是通过 U-Net 里的交叉注意力层注入:
# 交叉注意力的核心计算,形状标注对应单张 512x512 图的潜表示 # q: 来自图像特征,形状 [batch, heads, hw, dim] hw = 64*64 = 4096 # k/v: 来自文本编码器输出,形状 [batch, heads, 77, dim] attn = torch.softmax(q @ k.transpose(-1, -2) / (dim ** 0.5), dim=-1) # [batch, heads, hw, 77] out = attn @ v # [batch, heads, hw, dim]q是图像侧每个空间位置提出的「我想找什么样的信息」,k/v是文本侧 77 个 token 提供的候选。注意力权重算出来是一个 4096×77 的矩阵——每个图像位置对每个词分配一个相关度。写「红色的裙子」,与裙子相关的空间位置就会对red、dress两个 token 拿到更高的权重。
这也解释了为什么词序和词的位置有影响:77 个 token 里靠后的位置在长提示词中容易被稀释,靠前的词往往主导画面。所谓「提示词玄学」,本质是注意力分配的经验规律,不是随机性。
2.3 采样器在每一步算什么
去噪不是一步到位。模型每一步接收当前带噪潜变量和时间步t,预测出这一步的噪声,采样器再按自己的规则决定「减多少、往哪走」。PLMS(伪线性多步法)和 DDIM 的差别就在这里:
- DDIM 是确定性的一阶更新,每一步只依赖当前估计,步数少时容易显得生硬,但胜在稳定、可复现。
- PLMS 用上了前几步的历史信息做线性多步外推,同样步数下收敛更快,细节更丰富,代价是对步长序列更敏感,参数没配好反而会出现伪影。
所以--plms和--ddim不是「随便选一个」,而是两种数值积分策略。步数越高,积分越接近真实轨迹,但边际收益递减——--steps从 20 提到 50 往往肉眼可见变好,从 50 提到 100 多数时候只是更慢。
3. 环境与依赖:安装步骤背后的真实约束
3.1 为什么要 Python 3.7+ 和 PyTorch
原文要求 Python 3.7 或更高,这个下限来自 PyTorch 的版本支持矩阵。PyTorch 是这套流程的计算底座,所有张量运算、自动求导、CUDA 调用都经由它。装错版本最典型的后果不是报「版本不兼容」,而是跑到一半抛出算子缺失或者 CUDA 运行时错误——这类错误信息往往指向torch内部,让人误以为是代码问题。
一个稳妥的做法是:先确定显卡驱动支持的 CUDA 版本,再反过来选 PyTorch 的安装命令。官网给出的安装命令已经按 CUDA 版本分好组,直接复制对应那一行,不要凭记忆敲。
# 先确认驱动和可用的 CUDA 版本 nvidia-smi # 按 nvidia-smi 右上角显示的 CUDA Version 选择对应安装命令 # 示例(具体以官方安装页当前给出的命令为准) pip install torch torchvision torchaudio --index-url <官方对应 CUDA 版本的索引地址>nvidia-smi右上角的CUDA Version是驱动支持的上限,不是你装的 CUDA 工具包版本。装 PyTorch 时只要不超过这个上限即可,不必精确相等。低于上限一般能跑,高于上限才会失败。
装完必须验一次,别信「pip 说 Successfully installed」:
import torch print(torch.__version__) # 期望看到带 +cu 的版本号,例如 2.x.x+cu118 print(torch.cuda.is_available()) # 期望 True print(torch.cuda.get_device_name(0)) # 确认拿到的是独显而不是空值is_available()返回False是最常见的翻车点。原因通常是装成了 CPU-only 版本(版本号里没有+cu)。这种情况不用卸载重装整个环境,重新执行对应 CUDA 版本的安装命令覆盖即可。
3.2 虚拟环境不是可选项
原文把虚拟环境标为「可选但推荐」。实际的取舍更偏向必选。原因很具体:这套流程对torch、transformers、diffusers的版本组合敏感,而这些库同时也是其他项目的常客。系统级 Python 里装过的旧版numpy或者别的torch版本,会以「已满足依赖」的姿态让 pip 跳过安装,最后报出一堆莫名其妙的AttributeError。
# 创建隔离环境,-p 指定解释器可以避免用到系统里那个版本不对的 python python -m venv stable-diffusion-env # Linux / macOS 激活 source stable-diffusion-env/bin/activate # Windows 激活(PowerShell 用 .\ 前缀) # stable-diffusion-env\Scripts\activate # 激活后确认解释器路径落在环境目录内 which python # Windows 用 where python最后那步验证很关键。激活失败时which python仍指向系统解释器,之后所有pip install都装错地方,而你看不出任何异常。
3.3 代码仓库与模型权重是两回事
克隆代码库只拿到脚本和网络结构定义,模型权重需要单独下载。这是两个独立的资源,很多人卡在这里:脚本跑起来第一句就在找权重文件,找不到直接退出。
git clone <代码仓库地址> cd stable-diffusion pip install -r requirements.txtrequirements.txt里的依赖是锁定版本的,不要手动升级其中某个包。这套代码对transformers的 API 变化尤其敏感,升一个主版本可能整条推理链就断了。
权重文件通常几百 MB 到数 GB 不等,放在仓库约定的目录下(具体路径以仓库 README 为准),运行时通过参数或配置文件指定。下载后的校验习惯值得养成:对比文件大小与官方给出的是否一致,压缩包先解压再确认结构,避免把半个文件当成完整权重喂进去——那类错误往往表现为生成结果全是灰噪声,而不是直接报错。
4. 从提示词到出图:参数怎么改、失败看哪里
4.1 一条命令里各参数的作用域
python scripts/txt2img.py \ --prompt "a fantasy landscape, volumetric light, detailed" \ --plms \ # 采样器:PLMS 多步外推,步数少时收敛更快 --steps 50 \ # 去噪步数,直接线性拉长耗时 --n_samples 1 \ # 一次生成几张,显存按此倍数增长 --n_iter 1 \ # 迭代轮数,与 n_samples 相乘才是总张数 --H 512 --W 512 \ # 潜空间分辨率决定显存峰值 --seed 42 # 固定随机种子,便于对比参数效果--n_samples和--n_iter常被混淆:前者是一批同时进显存的张数,直接影响显存占用;后者是循环轮数,逐轮串行。想省显存就调n_iter,想提吞吐才调n_samples。
--seed在调参阶段几乎是必需品。不固定种子,你改了--steps看到画质变化,无法判断是步数的功劳还是换了一张随机初始噪声。控制变量,一次只动一个参数,是这个流程里最基本的排查素养。
4.2 采样器与步数的组合边界
| 采样器 | 适合步数 | 特点 | 典型问题 |
|---|---|---|---|
| DDIM | 50~200 | 确定性更新,结果可复现 | 步数少时细节缺失、画面发灰 |
| PLMS | 20~50 | 多步外推,同等步数细节更多 | 步数过低或与调度不匹配时出现伪影 |
这张表能解释一类常见困惑:换了采样器但没改步数,效果反而变差。PLMS 在 20 步左右的收益最明显,硬拉到 100 步既慢又未必更好;DDIM 本身一阶,步数给少了就明显不够。参数之间是耦合的,不是各自独立的最优值。
4.3 资源不足时的真实表现
原文提到没有高性能 GPU 会「非常缓慢」。更准确的说法是:显存不足会先崩,然后才是慢。显存不够时的报错通常是CUDA out of memory,伴随一个「已分配/保留」的数值明细。处理顺序是这样的:
- 降
--H/--W,从 512 往下调,这是对显存影响最大的单一变量,注意部分权重是在 512 上训练的,降太多结构会走形; - 降
--n_samples到 1,把批量生成改成分次生成; - 关掉其他占显存的进程,浏览器硬件加速和视频播放都会占一块;
- 确认没有在 CPU 上跑——
is_available()为False时程序可能不报错,只是慢到你以为卡死了。
纯 CPU 也能出图,只是单张可能从几十秒变成十几分钟。这条路适合验证流程是否跑通,不适合实际产出。
5. 避坑清单:五类真实翻车现场
5.1 报「找不到模块」但 pip 明明装过
现象:ModuleNotFoundError: No module named 'xxx',可pip list里能看到这个包。
原因:装了多个解释器,pip和python指向不同环境。虚拟环境激活失败、或者用pip3/python3混用时特别容易发生。
解决:统一用python -m pip install xxx的形式,保证 pip 属于当前解释器;再用python -c "import sys; print(sys.executable)"确认解释器路径落在环境目录里。
5.2 生成结果全是灰噪声或纯色块
现象:流程不报错,输出图却像电视雪花。
原因:权重文件不完整、路径指到了错误文件、或者模型配置里的参数与权重不匹配。潜空间去噪的每一步都依赖上一状态,权重出错会在解码后放大成完全无意义的图像。
解决:核对权重文件大小与来源一致;确认配置文件里的模型参数与下载的权重版本对应;先用官方示例提示词跑一次,排除提示词因素。
5.3 改了半天参数,画质毫无变化
现象:调--steps、换采样器,出图几乎一样。
原因:没固定--seed。每轮初始噪声都不同,参数带来的微小差异被随机性淹没。
解决:固定种子,一次只改一个参数,做成对照。想验证某个采样器是否真的更好,应该在同一组种子下对比多张,而不是各跑一张就下结论。
5.4 显存明明够,还是 OOM
现象:显存总量看起来远大于需求,仍然CUDA out of memory。
原因:显存被其他进程占着,或者上一次运行的残留没释放;也有的是分辨率设成了非 2 的幂次附近导致中间张量尺寸膨胀。
解决:先nvidia-smi看占用,清掉残留进程;分辨率优先取 512、768 这类常用值;--n_samples降到 1 再逐步加。
5.5 提示词写了但画面里没有
现象:提示词里的关键物体完全不出现,或者只出现一部分。
原因:文本条件通过交叉注意力注入,77 个 token 的容量有限,堆太多关键词会互相稀释;另外词的位置越靠后权重衰减越明显。
解决:把最重要的主体和属性放前面,删掉冗余修饰;长描述拆成更聚焦的短句;必要时用负面提示词排除干扰元素,而不是不断往正面提示词里加词。
6. 设计取舍:为什么这套流程注定「不好装」
稳定扩散的安装体验一直被人吐槽,但它其实是一组合理取舍的结果。模型本身是研究导向的开源实现,脚本直接暴露网络结构、采样器、调度器和权重加载逻辑,好处是可解释、可改造,代价是没有任何一层替用户兜底。相比之下,封装过的图形界面把这些参数藏起来,新手更容易跑通,但遇到is_available()为False这类问题时,反而无从下手。
第二个取舍是精度与成本的平衡。潜空间压缩让消费级显卡能参与生成,代价是高频细节的损失;DDIM 求稳、PLMS 求快,代价是参数之间必须搭配着调;CPU 也能跑,代价是时间成本高到不实用。这些都不是缺陷,是在有限算力下做出的优先级排序。理解排序,就能判断自己遇到的到底是 bug 还是预期的边界。
第三个取舍值得单独提:这个生态里版本漂移很快。代码仓库、依赖清单、权重格式、采样器实现,任何一环更新都可能让一份旧教程失效。所以真正可迁移的能力不是记住某条命令,而是养成验证习惯——装完先验torch.cuda.is_available(),跑图前先固定种子,出问题先看解释器路径和权重完整性。
我自己踩过最深的一次坑,是在一个装了两套 Python 的机器上反复重装依赖,折腾了大半天,最后发现pip从头到尾都装在另一个解释器里,代码压根没读到新装的包。从那以后我每次建环境,都强制走一遍「建环境、激活、which python确认路径、python -m pip install」这套动作,不再图省事跳过。
这份资料里把环境准备、依赖安装、代码与模型下载、txt2img.py的参数逐条拆开讲了一遍,配合上面的机制理解去读,每条命令都能对应到潜空间里正在发生的事。想上手跑通第一张图,从它开始逐条执行就够了。希望帮到你。
本文还有配套的精品资源,点击获取