005-建立YOLO11n基线-固定数据参数随机种子和结果目录
005-建立 YOLO11n 基线:固定数据、参数、随机种子和结果目录
本文基于 Ultralytics
8.3.253和 YOLO11n 进行整理,目的是在正式做注意力、Neck、Backbone、Loss 等改进前,先建立一套可重复对比的训练基线。后续所有改进实验都应该和这套基线在同一数据集、同一训练参数和同一评价方式下比较。
摘要
很多 YOLO 改进实验最容易忽略的一步,不是模块代码,而是 baseline。没有固定数据划分、随机种子、训练轮数、输入尺寸和结果目录,后面即使某个模块跑出了更高的 mAP,也很难判断是结构真的有效,还是训练条件发生了变化。
本文从工程复现实验的角度,使用 Ultralytics 8.3.253 中的 YOLO11n 作为基础模型,整理一套适合 Windows 环境的 baseline 建立流程。内容包括代码版本确认、数据集固定、训练参数固定、CLI 与 Python 两种训练方式、结果目录说明、实验记录表和常见问题排查。本文不填写任何虚构指标,所有 mAP、Precision、Recall 都以读者自己训练后的 results.csv 为准。
关键词: YOLO11、Ultralytics 8.3.253、YOLO11n、baseline、目标检测、results.csv、随机种子
一、为什么改进前必须先建立 baseline
后面做 YOLO11 改进时,经常会遇到下面几种情况:
- 加了注意力机制后 mAP50 变高,但 mAP50-95 没变;
- 换了 Neck 后参数量增加,训练显存也增加;
- 某个模块第一轮实验看起来有效,第二次复现又不明显;
- 只换了数据增强参数,却误以为是模型结构带来的提升。
这些问题本质上都和基线不稳定有关。一个合格的 baseline 至少要固定下面这些内容:
| 固定项 | 为什么要固定 |
|---|---|
| 数据集划分 | train、val、test 一旦变化,指标不能直接比较 |
| 模型版本 | YOLO11n、YOLO11s 等模型规模不同,不能混着对比 |
| 代码版本 | Ultralytics 不同版本的训练参数和解析逻辑可能变化 |
| 训练轮数 | epoch 不一致会影响收敛程度 |
| 输入尺寸 | imgsz 会影响小目标、显存和速度 |
| batch | batch 变化会影响训练稳定性和显存占用 |
| 随机种子 | 减少随机初始化、数据加载顺序带来的波动 |
| 结果目录 | 方便追踪每次实验的权重、曲线和日志 |
baseline 不是为了追求最高指标,而是为了让后面的每一次改动都有一个清楚的参照物。
二、本文使用的版本说明
本文统一使用以下工程环境:
| 项目 | 说明 |
|---|---|
| 操作系统 | Windows 10 / Windows 11 |
| YOLO 框架 | Ultralytics 8.3.253 |
| 基础模型 | YOLO11n |
| 训练任务 | 目标检测 detect |
| 推荐安装方式 | 源码可编辑安装 pip install -e . |
| 主要结果文件 | args.yaml、results.csv、results.png、weights/best.pt、weights/last.pt |
如果后续你要改源码,例如注册新模块、修改 YAML 或改检测头,建议使用源码可编辑安装:
cd C:\Users\你的用户名\Downloads\ultralytics-8.3.253
pip install -e .
这条命令的作用是让当前 Python 环境直接使用本地源码目录。后续你修改 ultralytics/nn/tasks.py、ultralytics/nn/modules/ 或模型 YAML 时,不需要每次重新打包安装。
安装完成后可以检查版本:
yolo checks
也可以用 Python 检查当前导入的是哪个路径:
import ultralytics
print(ultralytics.__version__)
print(ultralytics.__file__)
这里重点看两件事:版本是否为 8.3.253,以及 ultralytics.__file__ 是否指向你正在编辑的源码目录。
三、先固定数据集目录和 data.yaml
为了让后面的实验可以公平比较,数据集划分不要在每次实验前重新随机划分。建议第一次划分好以后,就固定目录结构:
datasets/
my_dataset/
images/
train/
val/
test/
labels/
train/
val/
test/
data.yaml
YOLO 标签文件需要和图片文件一一对应,例如:
images/train/000001.jpg
labels/train/000001.txt
data.yaml 可以按下面方式组织:
path: G:/datasets/my_dataset
train: images/train
val: images/val
test: images/test
names:
0: class_a
1: class_b
这几个字段要特别注意:
| 字段 | 说明 |
|---|---|
path | 数据集根目录 |
train | 训练集图片路径 |
val | 验证集图片路径 |
test | 测试集图片路径,可按实际情况保留 |
names | 类别编号和类别名 |
后续做改进时,尽量不要临时替换 val。模型好不好,主要看它在同一个验证集上的表现。验证集变了,指标就不再是同一个参照系。
四、固定 YOLO11n baseline 训练参数
Ultralytics 8.3.253 默认训练参数中,seed=0,deterministic=True,epochs=100,imgsz=640,batch=16,workers=8。这些默认值可以作为第一套基线的起点。
我建议把 baseline 明确写成下面这组参数:
| 参数 | baseline 建议值 | 说明 |
|---|---|---|
model | yolo11n.pt | 使用官方 YOLO11n 预训练权重 |
data | 自己的 data.yaml | 固定同一份数据集配置 |
epochs | 100 | 后续单模块实验保持一致 |
imgsz | 640 | 常用输入尺寸,兼顾速度和效果 |
batch | 16 | 显存不足时可以降低,但要记录 |
device | 0 | 使用第 0 张显卡 |
workers | 8 | Windows 卡住时可改为 0 或 2 |
seed | 0 | 固定随机种子 |
deterministic | True | 尽量保持可复现 |
project | runs/yolo11_baseline | 单独存放基线结果 |
name | yolo11n_s0_e100_i640 | 从目录名就能看出关键信息 |
exist_ok | False | 避免覆盖旧实验 |
amp | True | 默认开启混合精度训练 |
plots | True | 保存曲线图和验证可视化结果 |
如果你的显卡显存较小,可以优先调整 batch,但不要同时改很多变量。比如从 batch=16 降到 batch=8,实验记录表中就要写清楚。
五、使用 CLI 启动 baseline 训练
在 Windows 终端中,可以使用下面命令启动训练:
yolo detect train model=yolo11n.pt data=G:/datasets/my_dataset/data.yaml epochs=100 imgsz=640 batch=16 device=0 workers=8 seed=0 deterministic=True project=runs/yolo11_baseline name=yolo11n_s0_e100_i640 exist_ok=False cache=False close_mosaic=10 amp=True plots=True
这条命令的重点不在于参数多,而是把会影响实验对比的参数全部显式写出来。
几个容易忽略的参数说明如下:
| 参数 | 说明 |
|---|---|
seed=0 | 固定随机种子,减少不同训练之间的随机波动 |
deterministic=True | 开启确定性相关设置,速度可能略慢,但更适合做对比实验 |
project 和 name | 控制结果保存位置,避免所有实验都堆在 runs/detect/train |
exist_ok=False | 同名目录存在时不直接覆盖,防止旧结果被冲掉 |
cache=False | 第一套 baseline 先不缓存,避免不同机器内存条件影响复现 |
close_mosaic=10 | 最后 10 个 epoch 关闭 mosaic,沿用当前默认思路 |
如果 Windows 下数据加载卡住,可以把 workers=8 改成:
workers=0
这会降低数据加载并行度,但能规避一部分 Windows 多进程问题。修改后要在实验表中记录,不要和 workers=8 的结果混在一起比较。
六、使用 Python 脚本启动 baseline 训练
如果你后续计划批量跑多个模型,建议把 baseline 写成一个固定脚本,例如 train_yolo11n_baseline.py:
from ultralytics import YOLO
def main():
model = YOLO("yolo11n.pt")
model.train(
data=r"G:\datasets\my_dataset\data.yaml",
epochs=100,
imgsz=640,
batch=16,
device=0,
workers=8,
seed=0,
deterministic=True,
project=r"runs\yolo11_baseline",
name="yolo11n_s0_e100_i640",
exist_ok=False,
cache=False,
close_mosaic=10,
amp=True,
plots=True,
)
if __name__ == "__main__":
main()
运行方式:
python train_yolo11n_baseline.py
这段脚本和 CLI 命令做的是同一件事。Python 写法的好处是后续可以复制一份脚本,把 model 或 name 改成改进模型的配置,其他参数保持不变。
例如后面写某个注意力模块时,只改:
model = YOLO("yolo11n_attention.yaml")
name = "yolo11n_attention_s0_e100_i640"
其他训练条件不动,这样对比才有意义。
七、训练完成后应该保存哪些文件
Ultralytics 8.3.253 训练完成后,结果目录大致如下:
runs/
yolo11_baseline/
yolo11n_s0_e100_i640/
args.yaml
results.csv
results.png
labels.jpg
train_batch0.jpg
val_batch0_labels.jpg
val_batch0_pred.jpg
confusion_matrix.png
confusion_matrix_normalized.png
weights/
best.pt
last.pt
几个关键文件的作用如下:
| 文件 | 作用 |
|---|---|
args.yaml | 记录本次训练的全部参数,是复现实验的重要依据 |
results.csv | 每个 epoch 的 loss、Precision、Recall、mAP50、mAP50-95 等指标 |
results.png | 根据 results.csv 绘制的训练曲线 |
weights/best.pt | 根据验证指标保存的最佳权重 |
weights/last.pt | 最后一个 epoch 的权重,可用于断点续训 |
confusion_matrix.png | 混淆矩阵,用来观察类别混淆情况 |
val_batch*_pred.jpg | 验证集预测可视化图片 |
后续写改进文章时,建议至少保留 args.yaml、results.csv 和 weights/best.pt。这三个文件能够说明实验是怎么跑的、指标是多少、权重在哪里。
八、建立一张自己的 baseline 记录表
建议为整个 YOLO11 改进系列单独建立一张表。第一行就是 baseline,后面每个模块依次追加。
| 实验编号 | 模型配置 | 改动位置 | seed | epochs | imgsz | batch | mAP50 | mAP50-95 | 参数量 | GFLOPs | 备注 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| B001 | yolo11n.pt | 原始 YOLO11n | 0 | 100 | 640 | 16 | 按真实结果填写 | 按真实结果填写 | 按模型输出填写 | 按模型输出填写 | 第一套 baseline |
这里不要提前写提升百分比。baseline 训练完成后,再从 results.csv 中读取真实指标。
后续改进实验可以这样追加:
| 实验编号 | 模型配置 | 改动位置 | seed | epochs | imgsz | batch | mAP50 | mAP50-95 | 参数量 | GFLOPs | 备注 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| A001 | yolo11n_xxx.yaml | C3k2 后加入某模块 | 0 | 100 | 640 | 16 | 按真实结果填写 | 按真实结果填写 | 按模型输出填写 | 按模型输出填写 | 与 B001 对比 |
这样整理的好处是非常明显的:文章中可以清楚说明“我只改了模型结构,其他训练条件不变”。读者也能判断实验是否公平。
九、如何重新验证 baseline 权重
训练完成后,可以单独运行验证命令:
yolo detect val model=runs/yolo11_baseline/yolo11n_s0_e100_i640/weights/best.pt data=G:/datasets/my_dataset/data.yaml imgsz=640 batch=16 device=0 plots=True
这一步会重新在验证集上计算 Precision、Recall、mAP50 和 mAP50-95,并生成验证相关图像。
如果你想看预测效果,可以运行:
yolo detect predict model=runs/yolo11_baseline/yolo11n_s0_e100_i640/weights/best.pt source=G:/datasets/my_dataset/images/val imgsz=640 conf=0.25 device=0 save=True
注意,predict 的 conf=0.25 主要用于推理展示,不能代替正式验证指标。正式写实验对比时,优先看 val 或训练过程中的 results.csv。
十、断点续训和重新训练要分开
如果训练中断,可以使用:
yolo detect train resume model=runs/yolo11_baseline/yolo11n_s0_e100_i640/weights/last.pt
resume 是继续原来的训练,不是开启新实验。它会尽量沿用上一次训练保存的参数和优化器状态。
如果你要重新跑一套 baseline,建议换一个 name,例如:
name=yolo11n_s0_e100_i640_run2
不要直接覆盖原目录。baseline 一旦被覆盖,后面所有改进实验的参照物就不清楚了。
十一、常见问题
1. 为什么同样参数训练两次,结果还是有小幅波动
深度学习训练中仍然可能受到 CUDA 算子、数据加载、硬件环境等影响。seed=0 和 deterministic=True 可以减少波动,但不代表所有机器上每个小数点都完全一致。
做改进实验时,重点看稳定趋势,不要只根据一次训练中的极小差异下结论。
2. batch 改了以后还能和 baseline 比吗
可以记录,但不建议直接作为公平对比。batch 会影响显存、梯度更新和训练稳定性。显存不足必须改 batch 时,建议 baseline 和改进模型都使用同一个 batch。
3. mAP50 提高但 mAP50-95 没提高,算不算有效
不能只看 mAP50。mAP50 的 IoU 阈值较宽松,mAP50-95 更严格,能更好反映定位质量。后面做结构改进时,建议同时记录 mAP50 和 mAP50-95。
4. 训练结果目录自动变成 train2、train3 怎么办
说明同名目录已经存在。为了避免覆盖旧结果,Ultralytics 会生成新的目录。建议自己显式设置 project 和 name,让每次实验的命名可读。
5. Windows 下训练卡在数据加载阶段
可以先把 workers 改成 0 或 2 试一下。如果这样能正常训练,说明大概率是多进程数据加载相关问题。改动后要记录在实验表中,后续对比实验也保持一致。
十二、总结
本文完成了 YOLO11n baseline 的建立流程:固定 Ultralytics 8.3.253 版本、固定数据集划分、固定训练参数、固定随机种子和结果目录,并整理了训练完成后需要保存的关键文件。
后续做 YOLO11 改进时,先不要急着比较“提升了多少”。正确顺序应该是:baseline 能稳定复现,改进模型能正常构建,训练参数完全一致,最后再用 results.csv 中的 Precision、Recall、mAP50 和 mAP50-95 做对比。
有了这套基线,后面的注意力机制、轻量卷积、Neck 融合、检测头和损失函数实验才会有统一参照。否则文章写得再热闹,也很难说明改进到底来自哪里。
更多推荐




所有评论(0)