# 模型微调读者操作指南：从起步包到验收关机

配套资料：[模型微调跟练资料](https://jingjinglearns.cc/learn/model-finetuning/)。术语：[英文缩写与中文解释](TERMS.md)。

**先选路线：** 第一次操作走主流程，直接使用已经审核的24张虚拟人物图；想学习制作数据，再走末尾的进阶分支。主流程不需要先重新生图，也不需要重新筛图。

本指南没有包含作者的真人照片。平台和模型不是同一回事：AutoDL租服务器，Hugging Face下载模型。需要按服务要求自行注册、登录或完成验证，不在聊天、截图或公共文档中填写密码。

> 验证边界：原实验已经在4090上完成训练与生成。本次整理的新起步包做了本地文件、数据、命令接口和归档检查，没有为了改教程再租一轮服务器。下载速度、镜像库存和当前单价需要你在租用前确认；不承诺所有机器复现相同像素、耗时或费用。

## 0. 开机之前，拿对文件

下载本教程配套的 [portrait-lora-starter-v1.zip](https://jingjinglearns.cc/learn/model-finetuning/portrait-lora-starter-v1.zip)，先放在自己电脑上。本包不包含现成训练成果，你将从随包数据开始训练。

起步包包含：训练脚本、固定模型版本、训练配置、24张审核通过的图及描述、数据清单、母图、术语表和本操作指南。不含现成训练权重、旧训练输出、大底模、虚拟环境或登录凭据。

也就是说，包里已经有“课本”，没有塞进“本轮考完的答案”。你仍需下载底模、实际运行训练并验收。

本文命令分别标注“云端终端”和“本机PowerShell”。云端终端优先通过SSH连接；登录后，窗口中的命令在服务器上执行。不要在尚未连接的本机PowerShell里执行Linux路径命令。

## 1. 租一张显卡，先设停止时间

1. 在AutoDL控制台进入实例列表，选择租用新实例。
2. 使用按量计费、单张RTX 4090、24 GB显存。不要误选多卡或长期包月；本指南仅验证过这套GPU配置。
3. 选择基础镜像：PyTorch 2.5.1、Python 3.12、Ubuntu 22.04、CUDA 12.4。这是原实验环境；若当前没有对应镜像，不要只按名字相似就认定兼容。
4. 确认磁盘空间和单价。脚本首次下载前要求至少18 GiB可用空间，还要留出训练输出与打包空间；原实验使用免费50 GB数据盘，没有购买扩容。
5. 实例运行后，先在实例操作菜单中设置并确认定时关机。首轮可以按2小时设置，前提是按当前显示单价计算后仍在自己的预算内；到期可能中断未完成的训练，应先保留足够余量。

本次历史单价为2.08元/小时。以这个价格估算，两小时GPU费用约4.16元，但这不是当前报价，也不包括你另买的服务。原实验预算上限15元，不等于建议先花满15元。

**确认点：** 实例显示运行中，只有一张所选显卡，定时关机设置已保存。按量实例按开关机计费，不是只在GPU运算时计费。[创建与运行入口](https://www.autodl.com/docs/quick_start/)、[官方计费说明](https://www.autodl.com/docs/price/)

## 2. 通过SSH连接，再上传起步包

1. 在AutoDL实例页复制自己实例的SSH登录命令，打开本机PowerShell，粘贴并执行。SSH的英文全称是 **Secure Shell**，即安全外壳协议。
2. 首次连接时先核对目标实例及主机指纹；不能确认时暂停，向平台核实，不要跳过校验。按提示输入该实例的登录密码，输入时不显示字符是正常现象。不要把密码写进命令或公开截图。
3. 登录成功后，这个窗口就是后文的“云端终端”。若本机提示找不到 `ssh`，先按平台[SSH连接说明](https://api.autodl.com/docs/ssh/)准备客户端，不要把云端命令直接粘贴到本机执行。
4. 上传文件可以另用网页：在运行中的实例上点击JupyterLab，左侧文件区从 `/root` 进入 `autodl-tmp` 文件夹，再点击上传按钮，上传本机的 `portrait-lora-starter-v1.zip`，等待完成。

SSH负责执行命令，JupyterLab用于文件和图片操作。这些入口以平台实际界面为准。[JupyterLab官方说明](https://api.autodl.com/docs/jupyterlab/)

**云端终端：先建立可重新接入的工作会话。** SSH本身不保证连接中断后训练继续；这里使用 **tmux（terminal multiplexer，终端复用器）**保留服务器上的工作会话。它不防止实例关机、进程报错或显存不足。[平台长任务提醒](https://api.autodl.com/docs/vscode/)、[tmux官方入门](https://github.com/tmux/tmux/wiki/Getting-Started)

```bash
tmux -V
```

若提示找不到命令，在本指南的Ubuntu实例内依次运行 `apt-get update` 和 `apt-get install -y tmux`，每条成功后再继续。然后首次创建会话：

```bash
tmux new-session -s portrait-lora-starter-v1
```

后续安装、下载和训练都在这个会话内执行。若提示同名会话已存在，不要重复创建。需要离开时，先按 `Ctrl+B`，松开后按 `D`，只是退出查看，不会结束会话中的训练。

重新SSH登录后，用下面的命令回到原会话；不要重新执行训练命令：

```bash
tmux attach-session -t portrait-lora-starter-v1
```

若提示会话不存在，先检查日志和进程，不要假定训练已完成或直接重跑。

**云端终端：先确认压缩包位置。**

```bash
ls -lh /root/autodl-tmp/portrait-lora-starter-v1.zip
```

应看到文件名和大小。如果提示 `No such file or directory`，回到文件区检查上传的位置，不要继续安装。

**云端终端：解压到一个全新的实验目录。**

```bash
python -c "from pathlib import Path; import zipfile; target=Path('/root/autodl-tmp/portrait-lora-starter-v1'); target.mkdir(); zipfile.ZipFile('/root/autodl-tmp/portrait-lora-starter-v1.zip').extractall(target)"
```

如果提示 `FileExistsError`，说明目标目录已经存在。先检查是否有自己的任务或成果，不要删除旧目录来绕过保护，也不要覆盖作者的实验目录。

```bash
cd /root/autodl-tmp/portrait-lora-starter-v1
ls
```

**确认点：** 能看到 `portrait.py`、`setup.sh`、`train.toml`、`model-lock.json`、`dataset`，而不是再套一层同名文件夹。

## 3. 先验数据，再装环境和下载模型

起步包的24张图片已有审核描述和校验清单。先做只读检查，不会启动训练：

```bash
python -c "from portrait import ROOT, validate_dataset; print('OK: reviewed images =', len(validate_dataset(ROOT / 'dataset')))"
```

**确认点：** 输出 `OK: reviewed images = 24`。如果提示图片、描述或清单不一致，停止，不要用修改校验值的方式绕过检查。

下面全部在同一个云端终端中执行。若平台提供了网络加速脚本，先启用；不存在时这段会跳过：

```bash
if [ -f /etc/network_turbo ]; then
  source /etc/network_turbo
fi
export HF_HOME=/root/autodl-tmp/hf-cache
export HF_HUB_DISABLE_XET=1
bash setup.sh
```

`setup.sh`会检查显卡、建立独立Python环境，并安装固定训练器版本及依赖。安装日志在 `logs/setup.log`。这段失败后不要继续训练。

```bash
source .venv/bin/activate
python portrait.py preflight
```

**确认点：** 环境检查正常结束，记录中 `cuda_available` 为 `true`，GPU型号正确，没有缺失依赖。如果是 `false`，先确认是否误用无卡模式或错误镜像。

```bash
python portrait.py download
```

**确认点：** 最后出现 `download_complete`。脚本下载固定版本的底模与参考图组件，不会自动接受需要你确认的许可。使用与分享前，应阅读对应仓库的许可和限制。

遇到下载超时，先看网络与剩余磁盘，不要连续开新实例。界面长时间不动时，也不要直接把“慢”当作“已失败”。

## 4. 20步测试：先证明流程能跑通

仍在已激活环境的云端终端运行：

```bash
python portrait.py train --smoke
```

训练日志写进文件，不会把完整进度条一直打印在当前窗口。查看日志可在本机另开一个PowerShell窗口，用同一实例的SSH登录命令连接。这个第二终端只看日志，不接入训练会话，运行：

```bash
tail -f /root/autodl-tmp/portrait-lora-starter-v1/outputs/smoke/train.log
```

在这个看日志的窗口按 `Ctrl+C` 只停止跟随日志，不是停止另一个窗口的训练。回到执行训练的第一个终端，等待它结束。

然后在第一个终端检查保存文件：

```bash
ls -lh outputs/smoke/*.safetensors
tail -n 20 outputs/smoke/train.log
```

**确认点：** 有权重文件，日志出现20步完成和保存信息，训练命令正常返回。遇到 `out of memory`（显存不足）、报错退出或没有保存文件，先停止排查，不能直接开始正式训练。

`Output run already exists` 表示这个输出目录已有记录。脚本故意不覆盖结果；若要重做，应使用新的实验目录，并重新核实预算。

## 5. 正式训练，再读取权重检查

```bash
python portrait.py train
```

需要看日志时，在第二个终端运行：

```bash
tail -f /root/autodl-tmp/portrait-lora-starter-v1/outputs/run01/train.log
```

本配置最多1200步，400、800、1200步各保存一次。原实验正式运行含加载和保存约11分37秒，这不是你的机器的倒计时承诺。

结束后，回到第一个终端：

```bash
ls -lh outputs/run01/*.safetensors
python inspect_run.py
```

**确认点：** 权重检查正常结束，列出的权重均为 `all_tensors_finite: true`。这证明权重文件能读到且数值未发现异常，不证明人物已经足够像。

这几个文件名的含义：

| 文件 | 含义 |
| --- | --- |
| `vprsn01-step00000400.safetensors` | 第400步保存的人物权重 |
| `vprsn01-step00000800.safetensors` | 第800步保存的人物权重 |
| `vprsn01-step00001200.safetensors` | 第1200步保存的人物权重 |
| `vprsn01.safetensors` | 训练结束时另外保存的文件 |

## 6. 对照验收：这里给完整命令

先确认上述三个带步数的文件实际存在。仍在项目目录运行，下面不是带尖括号的占位模板：

```bash
python portrait.py evaluate \
  outputs/run01/vprsn01-step00000400.safetensors \
  outputs/run01/vprsn01-step00000800.safetensors \
  outputs/run01/vprsn01-step00001200.safetensors
```

脚本会生成底模与三个训练版本，四组各6张，总计24张。它不输入参考图，也不加载IP-Adapter。

在JupyterLab左侧进入 `portrait-lora-starter-v1/evaluation`，分别打开这些文件夹里的 `contact-sheet.jpg`：

```text
base
vprsn01-step00000400
vprsn01-step00000800
vprsn01-step00001200
```

比较同一位置的图，再打开原图检查细节。记录三个问题：是不是目标角色、衣服场景和姿势有没有执行、脸和身体有没有明显错误。

**确认点：** 四组图片都保存成功，并且你已看过结果。不要只凭损失值较低或最后一个文件步数最多来选。

已有 `evaluation` 结果时，重复执行会拒绝覆盖。先看已有图，别反复运行来“刷新”。

## 7. 重新加载出一张新图，先别关机

以下用原实验选定的800步版本演示。如果你的对照结果更适合其他版本，先确认对应文件存在，再替换 `--weight` 后的路径。

```bash
python portrait.py generate \
  --weight outputs/run01/vprsn01-step00000800.safetensors \
  --prompt "photo of vprsn01 woman wearing a green jacket, city park, soft daylight, waist-up portrait, natural skin texture" \
  --seed 1001
```

`--weight`指定人物文件，`--prompt`是生成要求，`--seed`是随机种子。新图在 `generated` 文件夹，旁边保存了生成参数。

**确认点：** 能打开新图片及其参数文件。此时再判断保存的LoRA是否确实可重新调用，不要拿训练图片充当新结果。

## 8. 下载结果、核对完整，最后关机

在云端项目目录执行：

```bash
python -m zipfile -c reader-results.zip outputs/run01 evaluation generated logs model-lock.json train.toml review.json
python -m zipfile -t reader-results.zip
sha256sum reader-results.zip
```

前两条将本轮权重和结果打包并检查压缩包，第三条输出SHA-256文件校验值。不含底模大文件、虚拟环境或数据缓存；24张原始训练图已在你下载的起步包里，起步包也要保留。

1. 在JupyterLab文件区找到 `reader-results.zip`，右键下载。它含多个权重文件，传输可能需要一段时间。
2. 在自己的电脑确认下载完成；不要把浏览器显示开始下载当作文件已保存。
3. Windows电脑可在PowerShell核对下载文件的校验值：

```powershell
Get-FileHash -Algorithm SHA256 -LiteralPath "$env:USERPROFILE\Downloads\reader-results.zip"
```

如果浏览器保存到其他目录，应选择实际文件路径。结果必须与云端 `sha256sum` 相同，大小写不同不影响比较。

4. 确认文件完整后，到AutoDL实例页点击关机，等待状态明确显示“已关机”，再查看实际扣费。不要点击释放或删除实例来代替普通关机。

**顺序不要颠倒：验收 → 新图验证 → 下载校验 → 关机确认。** 页面断开不等于训练停止，终端程序结束也不等于平台停止计费。

若下载失败，不要放着服务器空转到超预算。先在云端保留打包文件并确认平台数据保留规则，及时关机，之后用平台支持的文件传输方式取回。[官方上传与文件传输方式](https://api.autodl.com/docs/scp/)

## 以后还想继续出图

再次开机后，打开终端，进入同一项目目录并重新激活环境：

```bash
cd /root/autodl-tmp/portrait-lora-starter-v1
source .venv/bin/activate
```

然后执行第7步的生成命令即可，不必再运行训练。再次开机会计费，也可能受显卡库存影响；生成和下载完成后仍需关机。

## 进阶分支：自己生成候选图

这部分不属于第一次训练的必做步骤，会增加生图与筛选时间。应在预算内单独安排，不能在关机之后继续执行。

为了不覆盖主流程的数据，在已激活的云端环境里新建一个只用于数据探索的目录。目录已存在时先停下检查，不要覆盖：

```bash
python -c "from pathlib import Path; Path('/root/autodl-tmp/portrait-data-lab-v1').mkdir()"
cd /root/autodl-tmp/portrait-lora-starter-v1
cp portrait.py model-lock.json review.json /root/autodl-tmp/portrait-data-lab-v1/
cp -r anchors /root/autodl-tmp/portrait-data-lab-v1/
ln -s /root/autodl-tmp/portrait-lora-starter-v1/models /root/autodl-tmp/portrait-data-lab-v1/models
cd /root/autodl-tmp/portrait-data-lab-v1
python portrait.py expand --limit 6 --scale 0.55
```

在JupyterLab打开 `portrait-data-lab-v1/candidates/contact-sheet.jpg`，检查脸部、姿态和构图。合格后仍保持相同参考强度：

```bash
python portrait.py expand --limit 36 --scale 0.55
```

第二条会检查并跳过设置一致的已有图，再补齐候选。不要先0.75后0.55混在一个目录里；原实验的0.75是历史对照，不是这条读者流程的第一步。

如果要把新候选用于训练，必须重新逐张审图，不能直接沿用包里针对旧图写的 `review.json` 决定和描述。在JupyterLab右键 `review.json`，用编辑器打开：每张图填写 `accept`，入选图填写 `identity_ok`、`quality_ok` 和真实 `caption`。至少20张、最多30张，只有实际检查过的合格图才能填写 `true`。

这个分支目录没有既有 `dataset`，审核后才可以运行：

```bash
python portrait.py curate
```

它会生成新数据集和清单。**本分支到数据制作为止**；需要训练新数据时，再新建完整训练目录，不能混回主流程的历史输出。第一次操作不必为了走完进阶分支而继续付费。
