🚀 YOLO 多模型连续训练时报错与 NaN 问题全解析(附完整解决方案)
在深度学习实验中,我们经常需要在同一个脚本中连续训练多个模型(例如对比 YOLOv8、YOLOv9、YOLOv12 等性能)。然而,这种方式有时会带来意想不到的报错或数值问题,比如:
TypeError: list indices must be integers or slices, not list
或者更棘手的情况------模型虽然能训练,但损失全为 NaN,指标全为 0 。
这篇文章将带你一步步分析问题原因,并提供可直接使用的完整解决方案。
🧩 一、问题场景复现
我在同一个 Python 文件中,使用如下代码连续训练多个 YOLO 模型:
from ultralytics import YOLO models = [ "yolov8n.yaml", "yolov9n.yaml", "yolov12.yaml" ] for version in models: model = YOLO(version) model.train(data="data.yaml", epochs=50, imgsz=640)
结果第一个模型可以正常训练,但第二个或第三个模型初始化时就报错:
TypeError: list indices must be integers or slices, not list
更严重的是,有时虽然能启动训练,但所有的 loss 都是 NaN,AP、Precision、Recall 全为 0。
🔍 二、原因分析
这个问题表面上是 Python 类型错误,实际上是 YOLO 模型的内部状态残留问题。
YOLO 在初始化模型时(ultralytics/nn/tasks.py → parse_model 函数)会依赖一个通道列表 ch 来追踪每层的输入输出通道。如果在同一个进程中连续加载多个模型,旧模型的状态或 CUDA 缓存可能残留在内存中,导致后续模型解析时,ch 变量被污染。
简单来说,就是:
旧模型没被彻底释放,新模型加载时引用到了错误的中间变量类型。
这会导致:
-
list indices must be integers报错; -
或模型结构被错误初始化,权重出现 NaN;
-
或 BatchNorm 参数失效,导致所有损失为 NaN。
🧠 三、解决方案
✅ 方案一:每次训练后手动清理环境(推荐)
在每次模型训练后,显式清理显存与变量:
import torch, gc from ultralytics import YOLO models = [ "yolov8n.yaml", "yolov9n.yaml", "yolov12.yaml" ] for version in models: print(f"\n🔹 正在训练模型: {version}") model = YOLO(version) model.train(data="data.yaml", epochs=50, imgsz=640) # 手动清理内存和缓存 del model gc.collect() torch.cuda.empty_cache()
这样每次循环都会彻底释放旧模型内存,防止状态污染。
这是最简单、最稳定的解决方法。
✅ 方案二:分进程独立运行(彻底隔离)
如果你想完全隔离不同模型的训练环境,可以为每个模型启动独立进程。
import subprocess models = [ "yolov8n.yaml", "yolov9n.yaml", "yolov12.yaml" ] for version in models: cmd = f"python train_one.py --model {version}" subprocess.run(cmd, shell=True)
其中 train_one.py 内容为:
from ultralytics import YOLO import argparse parser = argparse.ArgumentParser() parser.add_argument("--model", type=str) opt = parser.parse_args() model = YOLO(opt.model) model.train(data="data.yaml", epochs=50, imgsz=640)
每个训练脚本独立运行、独立释放内存,互不干扰。
适合 GPU 资源充足、批量跑实验的场景。
⚠️ 方案三:不要在同一模型实例上反复加载不同结构
有些人会写:
model = YOLO() for cfg in ["yolov8n.yaml", "yolov12.yaml"]: model = YOLO(cfg) model.train(...)
这种写法最容易出问题,因为 YOLO 内部注册的层会被多次覆盖。
建议始终新建 YOLO 实例,不要复用旧变量。
💡 四、损失为 NaN 的原因补充说明
如果你在清理环境后依然出现 loss 为 NaN,可以进一步排查以下几点:
-
学习率太大 → 尝试减小 10 倍;
-
标签文件异常 → 检查是否有空标注或超出边界的坐标;
-
Batch Size 过大或显存溢出 → 调低 batch;
-
权重文件损坏 → 尝试重新下载或不加载预训练权重;
-
不同模型使用相同优化器状态 → 确保每次训练优化器独立初始化。
🧾 五、总结
| 问题 | 原因 | 解决方法 |
|---|---|---|
TypeError: list indices must be integers |
模型内部状态残留 | 每次训练后 del model; gc.collect(); torch.cuda.empty_cache() |
| 损失为 NaN | 旧状态污染 / 学习率太高 / 标签异常 | 清理显存 + 调整超参 |
| 多模型实验环境混乱 | 同一进程反复初始化不同结构 | 使用多进程或单独脚本 |
✨ 结语
在深度学习实验中,显存与模型状态的管理 是非常容易忽略的问题。
当我们在一个脚本中连续训练多个 YOLO 模型时,务必记得手动清理缓存或使用多进程隔离。
通过本文介绍的方法,相信你可以让多模型实验更加稳定、高效。🚀