【基础篇 26】第一次在服务器完成训练:准备数据、断线继续、检查成果与备份

YOLO从零到论文:模型改进与科研实战全攻略

YOLO基础篇 · A26

作者:迪菲赫尔曼

大家好,我是迪菲赫尔曼。

前面已经准备好数据、标签和配置,也理解了 Loss。现在把它们放到一次真正的服务器训练里。

第一次训练容易同时卡在几件事上:不知道程序读了哪份数据,不敢关掉本地电脑,终端没动静就反复启动,结束后又找不到 best.pt。这一篇沿着一次实际操作讲完:准备材料、进入会话、启动训练、读日志、重新连接、核对输出,最后取回成果。

先用 4 张训练图、4 张验证图的 COCO8 检查链路,再按自己的情况选择自采月饼或 A24 的完整宠物案例。这次先建立一条你能解释、能检查、能复查的训练流程。

1. 先确认环境、权重与数据

A13 的解释器、源码与 GPU 自检已经通过,服务器课程目录已有指定 weights/yolo26n.pt。本篇把 tmux、训练启动、日志观察和成果备份串成一次完整训练。

在远端终端执行:

bash 复制代码
cd /root/lanyun-tmp/yolo-study
source env/bin/activate
python -c "import sys, torch, ultralytics; print(sys.executable); print(ultralytics.__file__); print(torch.cuda.is_available())"
ls weights/yolo26n.pt

最后的 CUDA 可用项应为 True。找不到权重就先按 A15 上传,不能把网页链接保存成一个同名文本文件冒充权重。

第一次运行会同时检验环境、训练入口、数据读取、GPU 和输出保存。若自己的标注还在整理,先用固定小数据能减少同时排查的因素。

COCO8 只有 4 张训练图、4 张验证图。它是流程检查材料,不是足以证明研究效果的数据。 原类别表有 80 类,不能为了让文件看起来像月饼,就把它改成 0: mooncake。

从官方 COCO8 下载地址下载 coco8.zip,上传到服务器的 datasets 下,执行:

bash 复制代码
python -m zipfile -e datasets/coco8.zip datasets

确认 datasets/coco8/images/train、images/val 和对应标签都存在。将 coco8_data.yaml 保存为服务器的 datasets/coco8/data.yaml,保留完整的 names,再明确根路径为:

yaml 复制代码
path: /root/lanyun-tmp/yolo-study/datasets/coco8

这里只展示要核对的第一项,不能把这一行单独保存成完整数据配置。完整 train、val 与 names 都来自配套 YAML。

2. 把脚本放对地方,读懂第一次的参数

将 train_first.py 放到服务器课程根目录。不是放进源码包内部,也不是只保存在自己电脑里。

text 复制代码
yolo-study/
├── env/
├── code/ultralytics-8.4.183/
├── datasets/coco8/data.yaml
├── weights/yolo26n.pt
├── outputs/
└── train_first.py

脚本中真正训练的部分是:

python 复制代码
model = YOLO(str(model_path))
model.train(
    data=str(args.data.resolve()),
    epochs=3,
    imgsz=320,
    batch=2,
    device=0,
    workers=0,
    amp=False,
    plots=True,
    project=str(ROOT / "outputs"),
    name=args.name,
    exist_ok=False,
    seed=0,
)

其中 ROOT = Path(__file__).resolve().parent 以脚本所在目录为基准寻找权重。A13 已解释这个写法,所以脚本放错位置会改变相应路径。

参数 本次值 它控制什么
data 具体数据 YAML 读哪份数据、使用什么类别
epochs 3 计划训练多少轮
imgsz 320 训练输入尺寸约定,后续还受图像整理流程影响
batch 2 每批图片数量,不是每图目标数量
device 0 使用当前可见的第 0 张 GPU
workers 0 先不启用额外数据加载工作进程
amp False 第一次用明确的全精度路径检查
project/name outputs/实验名 保存结果的位置
seed 0 固定随机种子,不能由此承诺跨平台逐位一致

这些是入门检查设置,不是 RTX 4090 的最佳性能参数。后面 A31 再逐项改变,而不是第一次就同时追求最大 batch、最高分和最快速度。

exist_ok=False 用于避免直接复用已有输出。框架发现同名目录时可能递增名称,所以最后应以实际打印的保存目录为准,不能只凭自己写了什么 name 推断输出位置。

3. 先建立服务器会话,再启动训练

tmux 在服务器上管理终端会话。你可以让训练在会话内运行,再分离本地连接,之后重新接回。

它不能让一台已经关机的实例继续计算,也不能阻止平台回收资源。进程崩溃、磁盘满、训练报错,仍然需要检查和恢复。

把连接、会话和训练放进服务器这层盒子里,再看每个操作只影响哪里。

图解|断开连接、训练结束、实例关机分别影响哪一层。作用范围示意 · 会话存在不证明训练仍然健康

这是关系示意;会话存在不证明训练健康,日志/进程和平台状态仍要分别检查。

先运行 tmux -V 确认服务器已有它。没有时,按平台或系统管理员允许的方式安装;不要为了这一步改坏公共环境。

在远端终端执行:

bash 复制代码
tmux new -s yolo-shot

yolo-shot 是这里取的会话名,与磁盘上的项目文件夹名不是同一件事。若提示同名会话已经存在,先用 tmux ls 查看,再用 tmux attach -t yolo-shot 进入;不用为了消除提示先杀掉已有会话。

进入会话以后,再切到学习目录,执行 source env/bin/activate 激活课程环境。按 A13 打印 Python 与源码位置,确认没有因为新 Shell 回到另一份环境。

确认现在已经进入 yolo-shot,当前目录为课程根目录,并已激活 env。然后执行:

bash 复制代码
cd /root/lanyun-tmp/yolo-study
source env/bin/activate
mkdir -p outputs
python -u train_first.py --data datasets/coco8/data.yaml --name first_coco8_gpu > outputs/first_coco8_gpu.log 2>&1

这里 --data、--name 是本篇脚本接收的命令行参数,不是让你把它们写进 Python 文件中。

它们让同一份入口能明确选择数据和实验名,不需要第一次就复制四个几乎相同的脚本。--data 后的相对路径按执行命令的当前目录解释,所以前面要求先 cd 到课程根目录。

重定向日志后,当前窗口可能不再持续打印训练行,这是正常的。另开远端终端查看:

bash 复制代码
tail -n 40 /root/lanyun-tmp/yolo-study/outputs/first_coco8_gpu.log

同名日志会被覆盖,第二次实验换新名称;不要为了找结果反复启动同一条命令。

-u 减少 Python 输出缓冲;> 把标准输出写入文件;2>&1 把错误信息也写入同一日志。这是一条前台命令,没有新提示符不代表终端卡死。不要在日志尚未确认之前再次运行同一条训练命令。

4. 训练开始以后,按版本、数据和进度读日志

开头会打印 Ultralytics、Python、PyTorch、设备和训练配置。你应该能确认:固定源码 8.4.183、当前服务器 GPU、任务是 detect。

再看数据扫描:这份 COCO8 应读到 4 张训练图和 4 张验证图。若扫描的是自己的几百张月饼,说明你这次传入了另一份配置;那不一定错误,但不能再与本段的预期数量逐字比较。

模型结构和参数量会显示很多行。这一步不用背每一层,先确认没有在加载源码或建立模型时就终止。

常见列包括:

  • Epoch:当前轮数与总轮数。
  • GPU_mem:相关 GPU 显存显示,不是电脑硬盘剩余空间。
  • 各项 loss:当前训练过程中计算的误差项;A25、A29 会解释含义。
  • Instances:这一批里统计到的目标相关数量,不是整个数据集的图片总数。
  • Size:当前输入尺寸相关显示。

进度条达到一轮末尾后,通常会运行验证,再进入下一轮。验证打印 P、R、mAP 是在检查预测与标签,不是在继续给验证图反向更新参数。

Loss 不保证每轮都下降。只有几张图时,指标尤其容易波动;不要拿某一轮一个小数点就判断模块有没有用。

5. 分离、重新连接,并判断训练到底是什么状态

先按 Ctrl+B,松开,再按 D,将会话分离。不要在训练终端里打出文本 Ctrl+B D。

回到普通 SSH 终端后,可以查看:

bash 复制代码
tmux ls

以后重新登录,再连接:

bash 复制代码
tmux attach -t yolo-shot

看到会话存在,只证明会话还在。训练也可能已经成功结束或报错,继续看日志与进程。

对照一次真实的"分离---回来"

看到 [detached (from session yolo-shot)],说明退回外层终端;不是退出服务器,也不表示会话中曾经运行过的训练一定还健康。

再执行前面的 tmux attach -t yolo-shot,实际回到同一个会话:

图中依次显示课程目录、课程 Python 和当前会话名。这里只演示会话操作,没有启动训练;不能把它当成断线后模型仍在训练的证据。

bash 复制代码
cd /root/lanyun-tmp/yolo-study
tail -n 40 outputs/first_coco8_gpu.log

持续观察可以用 tail -f,退出查看按 Ctrl+C。注意:你退出的是这个查看命令,不是另一会话中的训练进程。

日志长时间不更新时,检查进程、设备、磁盘和数据读取。不能只看 GPU 占用就判断学习正常,日志里还需要有轮数、损失与验证进展。

重新连上以后,先判断状态,再决定下一步:

看到的情况 下一步怎么做
会话在,日志轮数仍推进 继续观察,不再启动第二个训练
会话在,日志已有完成信息与保存目录 检查成果文件,训练进程可能已经正常结束
会话在,日志末尾是 Traceback 从第一处相关报错排查,会话存在不代表训练成功
SSH 连不上 先看实例状态与连接信息,不能直接断言检查点丢失

tail -f 只是日志观察命令。在观察窗口按 Ctrl+C,结束的是观察;在训练所在窗口按相同按键,影响的则是训练本身。先辨认当前窗口,再操作。

6. 训练结束,确认这一轮真正留下了什么

实际保存目录下应有类似内容:

text 复制代码
outputs/first_coco8_gpu/
├── args.yaml
├── results.csv
├── results.png
└── weights/
    ├── best.pt
    └── last.pt

A27 会逐个解释。现在先检查文件存在且不是 0 字节;下一篇开头提供 predict_trained_detect.py 的完整附件与明确命令,用本次 best.pt 再做预测。不需要自己猜测怎样把训练入口改成预测入口。

best 是当前验证规则下选出的检查点,不是"已经达到论文效果"的证明。 last 也不能因为名字叫最后一个,就保证还保留完整的中断恢复状态,A33 会专门区分。

7. 再训练自己准备好的数据

这一节只给已经完成 A21---A24 自采数据检查的同学执行。 使用现成资料路线的同学,完成 COCO8 流程后直接阅读 A27,在 A27 训练 A24 的宠物数据;不必创建一个空的月饼目录,也不把 A22 单图练习当作训练集。

A24 已检查通过的配置应为:

text 复制代码
datasets/mooncake/data.yaml

其中 path 指向 datasets/mooncake/prepared,不是前面原始 raw 图片,也不是 COCO8。

继续使用同一份脚本:

bash 复制代码
python -u train_first.py --data datasets/mooncake/data.yaml --name first_mooncake_gpu > outputs/first_mooncake_gpu.log 2>&1

这次应读到 A24 报告里的月饼数量,类别也应是你实际标注的 mooncake。

COCO8 的运行数字对应它自己的图片与类别;换成自采月饼以后,需要重新训练和验证,才能判断这份数据上的效果。想先完成一套资料齐全的真实数据练习,可以继续 A24、A27 与 R06 宠物头部检测连续案例:它有固定划分、GPU 训练、错误样本和对照记录,然后再迁移自己的月饼。

你可以用下面这张对应图,再检查一次自己跑的是哪条路线。

图解|COCO8检查路线与自采月饼路线分别保存什么。文件对应关系示意 · 输出以实际save_dir为准

没有完成自采数据检查,就先沿 COCO8 流程继续学习,再完成 A24 的数据准备和 A27 的训练排错,不需要创建空的月饼目录。

8. 训练失败与真正中断,分别处理

找不到 YAML,先查服务器文件与完整路径;找到 YAML 但图片不存在,再查配置里的根目录。CUDA 不可用,回到 A12/A13,不把 device=0 悄悄改为 CPU 后继续宣称 GPU 已经通过。

显存不足先记录参数、检查 GPU 进程,从 batch 开始逐项调整。训练结束但找不到结果,先读日志最后打印的实际保存目录,而不是在本地电脑搜索一个从未下载回来的文件。

先确认旧进程已经停止,避免重复训练写同一目录。检查 last.pt 是否完整,再按 A33 的恢复方式继续。

best.pt 用于选定模型,不自动等价于具备完整训练恢复状态;重新加载一个权重启动新训练,也与恢复优化过程不同。

后面的队列工具同样只管理命令状态;是否恢复训练内部状态,仍要明确指定检查点与模式。

完整报错读取方法见 A13。

先排除旧进程还在运行的情况,再处理真正的中断。恢复时需要哪些状态、为什么正常结束后的 last.pt 不一定适合续训,A33 会用真实中断例子展开。

9. 把成果取回本地,再检查资源状态

先在远端整理一个独立实验目录,保留配置、CSV、日志、权重和数据划分说明。

在本地终端执行示意命令:

bash 复制代码
scp -P 2222 -r root@203.0.113.10:/root/lanyun-tmp/yolo-study/outputs/my_run ./my_run_backup

用户名、地址、端口、远端路径都换成真实值。scp 端口参数是大写 -P;目标 ./my_run_backup 位于本地当前目录。

复制完成后,核对关键文件大小与 SHA-256。不要只看目录名字出现了,就认为所有大权重都传完了。

结束 Python 训练只停止计算进程,不自动停止租用实例。关闭 SSH 或 VS Code 也不等于停止实例。

备份确认完成后,按平台控制台或正式工具停止不需要的资源,并检查状态。磁盘、快照或其他关联资源是否继续计费,按当时规则分别核对。

释放或删除资源可能影响数据保留,先确认再执行。不同平台的停止和存储规则不同,需要按你当前使用的平台核对。

这一课完成以后,你应当能指出数据配置、初始化权重、真实保存目录和本地备份的位置。下一篇再打开 args.yaml、CSV、曲线和预测图,把这次训练的结果读明白。

会话操作参考 tmux 官方入门说明。



本篇完整代码与记录

按正文指定的路径与文件名保存以下内容,文件之间的目录关系保持一致。

配套练习/coco8_data.yaml

yaml 复制代码
train: images/train
val: images/val
names:
  0: person
  1: bicycle
  2: car
  3: motorcycle
  4: airplane
  5: bus
  6: train
  7: truck
  8: boat
  9: traffic light
  10: fire hydrant
  11: stop sign
  12: parking meter
  13: bench
  14: bird
  15: cat
  16: dog
  17: horse
  18: sheep
  19: cow
  20: elephant
  21: bear
  22: zebra
  23: giraffe
  24: backpack
  25: umbrella
  26: handbag
  27: tie
  28: suitcase
  29: frisbee
  30: skis
  31: snowboard
  32: sports ball
  33: kite
  34: baseball bat
  35: baseball glove
  36: skateboard
  37: surfboard
  38: tennis racket
  39: bottle
  40: wine glass
  41: cup
  42: fork
  43: knife
  44: spoon
  45: bowl
  46: banana
  47: apple
  48: sandwich
  49: orange
  50: broccoli
  51: carrot
  52: hot dog
  53: pizza
  54: donut
  55: cake
  56: chair
  57: couch
  58: potted plant
  59: bed
  60: dining table
  61: toilet
  62: tv
  63: laptop
  64: mouse
  65: remote
  66: keyboard
  67: cell phone
  68: microwave
  69: oven
  70: toaster
  71: sink
  72: refrigerator
  73: book
  74: clock
  75: vase
  76: scissors
  77: teddy bear
  78: hair drier
  79: toothbrush

配套练习/train_first.py

python 复制代码
import argparse
from pathlib import Path

from ultralytics import YOLO

ROOT = Path(__file__).resolve().parent
DATA = ROOT / "datasets" / "mooncake" / "data.yaml"
NAME = "first_mooncake_gpu"


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--data", type=Path, default=DATA)
    parser.add_argument("--name", default=NAME)
    args = parser.parse_args()
    model_path = ROOT / "weights" / "yolo26n.pt"
    print("Initial weights:", model_path)
    print("Data config:", args.data.resolve())
    model = YOLO(str(model_path))
    model.train(
        data=str(args.data.resolve()),
        epochs=3,
        imgsz=320,
        batch=2,
        device=0,
        workers=0,
        amp=False,
        plots=True,
        project=str(ROOT / "outputs"),
        name=args.name,
        exist_ok=False,
        seed=0,
    )
    print("Training output:", model.trainer.save_dir)


if __name__ == "__main__":
    main()
相关推荐
进击的荆棘17 分钟前
Linux系统——线程同步与互斥
linux·运维·服务器·策略模式·同步·互斥·posix
.道阻且长.35 分钟前
Linux基本开发工具:gdb和cgdb的使用
linux·运维·服务器·开发语言
小年糕是糕手36 分钟前
【AI】用 AI 做自己的个人网站(上):选模板、写提示词,做出第一版
人工智能·app·网页开发·codex·index·styles·0基础教程
硅谷秋水40 分钟前
RoboAtom:机器人学习的大规模原子-动作监督
人工智能·机器学习·计算机视觉·机器人
vipxieliang42 分钟前
可观测性与安全的融合:统一数据平台的建设实践
运维·openai·自动化运维
vipxieliang1 小时前
具身智能2026:从实验室演示到万台级量产
人工智能
lucas_AI1 小时前
花旗银行教你算 AI 的账:省下的时间要和审查成本、残余风险记在同一本账上
人工智能
叼烟扛炮1 小时前
Linux 学习笔记(五十四):内网穿透实战——用 frp 让外网访问你的私人电脑
linux·服务器·网络·笔记·学习
lucas_AI1 小时前
没人教过它化学立体几何,但它悄悄学会了:前沿 LLM 排构象已经超过经典力场
人工智能