conda activate poultry(PyCharm 会自动带)train.py 的函数参数if __name__ == "__main__"目标:确认机器认得你的显卡,并知道它支持哪个 CUDA 版本。
nvidia-smi
CUDA Version(这里是 12.4),第 3 步要照着它选 PyTorch 版本目标:把训练用的库装在独立环境里,不污染系统 Python。
conda create -n poultry python=3.10 -y conda activate poultry
(poultry) 就成功了。之后每一步都要在这个环境下执行,
重新开终端要先 conda activate poultrypython -m venv poultry poultry\Scripts\activate # Windows source poultry/bin/activate # Linux
目标:装一个能用 GPU 的 PyTorch。这一步最容易装错。
按第 1 步看到的 CUDA 版本,选不高于它的那一行执行。
# RTX 50 系 / Blackwell(驱动 CUDA ≥ 12.8)—— 必选这行 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu128 # RTX 20/30/40 系,驱动 CUDA ≥ 12.1 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121 # 更老的显卡(驱动 CUDA ≥ 11.8) pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118
sm_120,而 CUDA 12.1 的 PyTorch wheel 里
没有包含这个等级的计算核心。装错了会在训练开始时直接报
no kernel image is available for execution on the device。
显存再大、驱动再新都没用,必须用 cu128。
装完立刻验证,这一步不能跳过:
python -c "import torch;print(torch.__version__, torch.cuda.is_available(), torch.cuda.get_device_name(0))"
True。如果是 False,说明装成了 CPU 版:
先 pip uninstall torch torchvision -y 再重装,注意别漏掉 --index-url 那一截+cu128 / +cu121 才是 GPU 版;带 +cpu 就是装错了+cu128 了但训练时报 no kernel image,说明卡是 50 系却没装 cu128目标:装好训练框架,确认它能找到显卡。
pip install ultralytics yolo version yolo checks
yolo checks 会打印一张环境自检表:Python / torch / CUDA / 内存 / 磁盘,全部打勾即可No module named 'ultralytics' → 十有八九是忘了 conda activate poultry目标:拿到图像和标注文件。
下载地址见本页第 02 节(百度网盘,提取码 MAWH)。解压 .rar:
# Windows: 装 7-Zip 或 WinRAR,右键「解压到当前文件夹」即可 # Linux sudo apt install unrar -y unrar x data.rar
images/xxx.jpg 与 labels/xxx.txt,
用记事本打开 txt,里面应该是若干行 0 0.5123 0.4381 0.0864 0.1217 这样的数字<annotation><object>... 这种 XML,那是 VOC 格式,
需要先转成 YOLO 格式,本页不展开目标:让框架按约定的位置找到训练集和验证集。
Ultralytics 只认下面这种结构,目录名和层级不能改:
dataset/
├── data.yaml
├── images/
│ ├── train/ 训练图像
│ └── val/ 验证图像
└── labels/
├── train/ 与训练图像同名的 .txt
└── val/ 与验证图像同名的 .txt
关键点:图像和标签靠文件名对应(abc.jpg ↔ abc.txt),
不靠目录顺序。所以两边必须一起移动,绝不能只挪一边。
数据还没划分训练/验证集的话,用下面这段脚本按 9:1 随机划分
(把 SRC 改成你的数据目录):
# 保存为 split.py,然后 python split.py import random, shutil, pathlib SRC = pathlib.Path("raw") # 原始 images/ 与 labels/ 所在目录 DST = pathlib.Path("dataset") # 输出目录 RATIO = 0.9 # 训练集比例 imgs = sorted((SRC / "images").glob("*.jpg")) random.seed(0); random.shuffle(imgs) cut = int(len(imgs) * RATIO) for split, group in (("train", imgs[:cut]), ("val", imgs[cut:])): (DST / "images" / split).mkdir(parents=True, exist_ok=True) (DST / "labels" / split).mkdir(parents=True, exist_ok=True) for p in group: shutil.copy(p, DST / "images" / split / p.name) lab = SRC / "labels" / (p.stem + ".txt") if lab.exists(): shutil.copy(lab, DST / "labels" / split / lab.name) print(f"训练 {cut} 张, 验证 {len(imgs) - cut} 张")
目标:告诉框架数据在哪、有几类。
在 dataset/ 下新建 data.yaml,内容如下:
# Linux path: /root/data1/work/ultralytics-main/dataset train: images/train val: images/val # Windows 把 path 改成(注意用正斜杠,不要反斜杠) # path: D:/poultry/dataset names: 0: chicken
path 用绝对路径最省事;train / val 是相对 path 的子路径names 的编号必须和标注文件第一列对得上。只有一类,所以编号是 0目标:用 1 分钟、极少的数据确认整条链路是通的,再花几小时正式训练。
不要一上来就跑 200 轮。先用这条命令探路——只取 2% 数据、1 轮、小尺寸:
yolo detect train \ model=yolov8n.yaml \ data=dataset/data.yaml \ epochs=1 \ imgsz=320 \ batch=4 \ fraction=0.02 \ device=0 \ name=smoke
盯住输出里这两行:
目标:眼见为实。这是新手最容易翻车的地方——训练跑完了,才发现标签一张没读到。
冒烟测试结束后,打开它生成的那张预览图:
runs/train/smoke/train_batch0.jpg
labels/ 里的文件名和 images/ 里的是否完全同名(含大小写、扩展名)class cx cy w h,且后四个在 0~1 之间UTF-8 编码、行尾没有奇怪符号data.yaml 里 train: 指的是 images/train 而不是 labels/trainlabels.jpg 是标注分布图,能看出框的尺寸与位置分布是否合理目标:跑满 200 轮。这就是本课题各模型实际使用的命令。
yolo detect train \ model=yolov8n.yaml \ data=dataset/data.yaml \ epochs=200 \ imgsz=640 \ batch=48 \ device=0 \ optimizer=SGD \ lr0=0.01 \ lrf=0.01 \ momentum=0.937 \ weight_decay=0.0005 \ warmup_epochs=3.0 \ patience=50 \ close_mosaic=10 \ amp=true \ seed=0 \ deterministic=true \ workers=8 \ project=runs/train \ name=exp_yolov8n
换模型只改 model= 一处,比如 yolov8m.yaml、yolov9m.yaml、
rtdetr-l.yaml;同时把 name= 改掉,避免覆盖上次结果。
batch 48 → 32 → 16,还不行再降 imgsz 640 → 512目标:判断「一切正常」还是「需要干预」。
训练会按轮打印进度,几个判断标准:
box_loss / cls_loss / dfl_loss)。
中间抖动正常,只要趋势向下lr0 从 0.01 降到 0.001 重跑tail -f runs/train/exp_yolov8n/results.csv,
或等训练结束看 results.png训练结束(或中断)后目录里会有这些产物:
| 文件 | 看什么 |
|---|---|
| weights/best.pt | 验证指标最优的权重,最终要用的就是它 |
| weights/last.pt | 最后一轮的权重,用于续训 |
| results.png | 损失与指标总览曲线 |
| results.csv | 逐轮数据,本页成绩表就是从它汇总的 |
| val_batch0_pred.jpg | 验证集预测结果,最直观的效果检查 |
目标:评测、看图、导出部署格式。
# 1) 在验证集上重新评测, 得到与页面成绩表同口径的指标 yolo detect val model=runs/train/exp_yolov8n/weights/best.pt data=dataset/data.yaml # 2) 拿一批新图做预测(单张、目录、视频都行) yolo detect predict model=runs/train/exp_yolov8n/weights/best.pt source=test_images/ save=true # 3) 导出为 TorchScript, 便于部署到边缘设备 yolo export model=runs/train/exp_yolov8n/weights/best.pt format=torchscript
conf=0.25(只保留得分高于 0.25 的框)runs/detect/predict/ 下目标:不浪费已经跑过的轮数。
直接 Ctrl+C 停掉不会损坏数据,续训只要一条命令:
yolo detect train resume model=runs/train/exp_yolov8n/weights/last.pt
last.pt,不是 best.pt —— 续训要从最后一轮的完整状态
(含优化器动量、学习率位置)接上args.yaml,不用再写一遍参数目标:复现本页第 05 节的成绩表。
把模型名写成列表循环,逐个训练、互不干扰:
# 保存为 run_all.sh,然后 bash run_all.sh
#!/usr/bin/env bash
MODELS="yolov5n yolov5s yolov8n yolov8s yolov8m yolov9t yolov9s yolov10n rtdetr-l"
for m in $MODELS; do
echo "===== 开始训练 $m ====="
yolo detect train \
model=${m}.yaml data=dataset/data.yaml \
epochs=200 imgsz=640 batch=48 device=0 \
optimizer=SGD lr0=0.01 lrf=0.01 \
patience=50 close_mosaic=10 amp=true \
project=runs/train name=exp_$m
done
echo "===== 全部完成,结果在各 runs/train/exp_*/ 目录下 ====="
# Windows PowerShell 版
$models = "yolov8n","yolov8s","yolov8m"
foreach ($m in $models) {
yolo detect train model="$m.yaml" data=dataset/data.yaml `
epochs=200 imgsz=640 batch=48 device=0 `
optimizer=SGD lr0=0.01 patience=50 `
project=runs/train name="exp_$m"
}
跑完把各目录的 results.csv 收进一个文件夹,执行
python tools/build_poultry_metrics.py(见第 08 节说明),
本页的对比表就会自动更新。