简介:火焰数据集(含标注好的标签)面向从事目标检测的开发者与研究者,尤其适合使用 YOLOv5 训练火焰识别模型的场景,可用于火灾预警、视频监控等实际项目。资源包共 5260 个文件,包含 1853 张 jpg 图像、1853 个 txt 标注文件与 1553 个 xml 标注文件,txt 与 xml 分别对应 YOLO 与 VOC 两种标注格式,便于直接接入不同训练框架,压缩包约 194.03MB。目前已有 4904 人学习下载。数据集覆盖多种光照与场景下的火焰样本,标注信息包含火焰位置、形状与大小,使用 YOLOv5 训练可达到 mAP@.5 为 0.953、mAP@.5:.95 为 0.679 的精度表现。读者可据此完成数据预处理、增强、模型调优与评估的完整流程,并参考指标结果快速验证自己的检测方案,为火焰检测及同类目标检测任务提供可复用的数据基础与训练参考。1. 火焰数据集与 YOLOv5 训练实战:从标注文件到可推理模型如果你正在做火焰检测相关的视觉项目,大概率绕不开两件事:一是找到一份标注质量靠谱的数据集,二是把它塞进 YOLOv5 跑通训练和推理。我最近拿到一份火焰数据集,里面已经包含标注好的标签文件,目录结构是标准的 images/labels 配对形式,标签格式为 YOLO 的 txt 归一化坐标。这意味着不需要自己从零标注,直接就能进入训练环节。这份资源适合两类人:刚接触目标检测、想拿一个真实场景数据集练手的新手,以及需要快速验证火焰检测方案可行性的开发者。下面我会按实际拆项目的顺序,把数据检查、环境搭建、训练配置、推理验证和二次开发改造讲清楚,让你拿到手就能跑,跑完还能改。2. 数据集结构与标注格式:先搞清楚手里有什么2.1 目录组织与文件对应关系拿到数据集后第一件事不是急着写训练脚本,而是把目录结构摸清楚。这份火焰数据集常见做法是分成训练集、验证集,有时还有测试集,每个子集下再分 images 和 labels 两个文件夹。images 里放 jpg 或 png 原图,labels 里放同名的 txt 标注文件。文件名必须一一对应,差一个字符都会导致训练时找不到标签。一个典型的目录长这样:fire_dataset/ ├── images/ │ ├── train/ │ │ ├── fire_0001.jpg │ │ └── fire_0002.jpg │ └── val/ │ ├── fire_0101.jpg │ └── fire_0102.jpg ├── labels/ │ ├── train/ │ │ ├── fire_0001.txt │ │ └── fire_0002.txt │ └── val/ │ ├── fire_0101.txt │ └── fire_0102.txt └── data.yaml这里有个血泪经验:很多人解压后直接把 images 和 labels 平铺在一起,结果 YOLOv5 的 dataloader 按路径拼接时找不到文件。YOLOv5 默认会去 images 路径里把/images/替换成/labels/再找同名 txt,所以目录层级必须严格对应。如果你拿到的数据集结构不同,要么调整目录,要么在 data.yaml 里显式指定路径。2.2 YOLO 标注格式逐字段解读打开任意一个 labels 下的 txt 文件,你会看到类似这样的内容:0 0.512 0.634 0.221 0.318 0 0.734 0.412 0.156 0.287每一行代表一个目标框,五个字段含义分别是:类别索引、中心点 x 归一化坐标、中心点 y 归一化坐标、框宽归一化、框高归一化。归一化是指除以图片宽高,所以数值都在 0 到 1 之间。类别索引从 0 开始,这份火焰数据集如果只有火焰一个类别,那所有行的第一个数字都是 0。这里容易翻车的地方是坐标越界。有些标注工具导出的坐标可能因为图片旋转或裁剪出现大于 1 或小于 0 的值,YOLOv5 训练时虽然会做裁剪,但最好提前检查一遍。我一般会写个脚本扫一遍所有标签文件:import os label_dir = "fire_dataset/labels/train" bad_files = [] for fname in os.listdir(label_dir): if not fname.endswith(".txt"): continue path = os.path.join(label_dir, fname) with open(path, "r") as f: for line_no, line in enumerate(f, 1): parts = line.strip().split() if len(parts) != 5: bad_files.append((fname, line_no, "字段数不对")) continue cls, x, y, w, h = map(float, parts) # 检查归一化坐标是否在合理范围 if not (0 <= x <= 1 and 0 <= y <= 1 and 0 < w <= 1 and 0 < h <= 1): bad_files.append((fname, line_no, f"坐标越界: {x},{y},{w},{h}")) print(f"发现异常文件数: {len(bad_files)}") for item in bad_files[:10]: print(item)这段脚本做三件事:遍历标签目录、检查每行字段数是否为 5、检查归一化坐标是否在合法区间。参数上,label_dir换成你自己的路径即可。如果输出异常文件很多,说明标注质量有问题,需要回到标注环节修复,否则训练出来的模型会出现莫名其妙的漏检。2.3 data.yaml 配置与类别映射YOLOv5 训练依赖一个 data.yaml 文件,里面写明训练集、验证集路径和类别信息。这份火焰数据集通常已经附带,但路径可能需要根据你的实际存放位置调整。一个标准的写法:train: ./fire_dataset/images/train val: ./fire_dataset/images/val nc: 1 names: ['fire']nc是类别数量,names是类别名称列表。如果数据集里除了火焰还有烟雾,那 nc 改成 2,names 写成['fire', 'smoke']。注意 names 的顺序必须和标签文件里的类别索引一致,索引 0 对应 names 第一个元素。我见过有人把顺序写反,训练 loss 正常下降但推理时把烟雾框成火焰,排查半天才发现是这里错了。提示:修改 data.yaml 后,建议用python -c "import yaml; print(yaml.safe_load(open('data.yaml')))"快速验证 YAML 语法,避免缩进错误导致训练启动失败。3. 环境搭建与 YOLOv5 训练:从零跑通第一个 epoch3.1 依赖安装与版本选择YOLOv5 对 PyTorch 和 CUDA 版本比较敏感,版本不匹配会直接报错。我一般会先确认显卡驱动支持的 CUDA 版本,再装对应的 PyTorch。常见做法是用 conda 建一个独立环境,避免污染系统 Python:conda create -n fire_yolo python=3.9 -y conda activate fire_yolo # 根据你的 CUDA 版本选择,这里以 CUDA 11.8 为例 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 克隆 YOLOv5 仓库并安装依赖 git clone https://github.com/ultralytics/yolov5.git cd yolov5 pip install -r requirements.txt参数说明:python=3.9是 YOLOv5 比较稳定的 Python 版本,3.10 以上有时会遇到依赖包不兼容。--index-url指定 PyTorch 官方源,比默认源快很多。如果你没有 GPU,把 cu118 换成 cpu 即可,但训练速度会慢到怀疑人生,火焰数据集这种几百上千张图的规模,CPU 训练可能要跑一整天。安装完成后用一行命令验证环境:python -c "import torch; print(torch.__version__, torch.cuda.is_available())"输出里True表示 GPU 可用。如果显示False,先检查驱动,再检查 PyTorch 版本是否匹配。3.2 训练命令与关键参数调优环境就绪后,把 data.yaml 放到 YOLOv5 根目录,然后启动训练。最基础的命令:python train.py \ --data data.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --project runs/train \ --name fire_exp逐参数解释:--data指向你的 data.yaml;--weights指定预训练权重,yolov5s 是最小的模型,速度快适合快速验证,如果精度不够可以换 yolov5m 或 yolov5l;--img 640是输入图片尺寸,火焰数据集如果图片分辨率很高,可以调到 1280,但显存占用会翻倍;--batch 16是批次大小,显存不够就降到 8 或 4;--epochs 100是训练轮数,火焰检测这种单类别任务通常 100 到 300 轮足够收敛;--project和--name决定输出目录。训练过程中终端会打印每个 epoch 的 loss 和 mAP 指标。重点看三个值:box_loss、obj_loss、cls_loss 是否稳定下降,以及 mAP@0.5 是否在上升。如果 loss 震荡剧烈,常见原因是学习率太大或 batch 太小,可以加--lr0 0.001降低初始学习率。如果 mAP 早早卡住不涨,可能是数据量不够或标注质量差,需要回头检查数据集。3.3 训练过程监控与中断恢复YOLOv5 训练时会在runs/train/fire_exp下生成一堆文件,其中results.csv记录了每个 epoch 的详细指标,weights/下保存 best.pt 和 last.pt。我习惯用 TensorBoard 实时看曲线:tensorboard --logdir runs/train浏览器打开对应端口就能看到 loss 和 mAP 曲线。如果训练到一半断电或手动中断,可以用--resume从 last.pt 继续:python train.py --resume runs/train/fire_exp/weights/last.pt这里有个坑:--resume会读取原训练的所有参数,如果你中途改了 data.yaml 或换了数据集,resume 后可能报错或行为异常。稳妥做法是重新开一个实验目录从头训练,别偷懒。注意:训练前务必确认data.yaml里的路径是绝对路径或相对于 YOLOv5 根目录的正确相对路径。路径错误时 YOLOv5 会直接报FileNotFoundError,但有时会静默跳过部分数据,导致训练集实际数量对不上。4. 推理验证与效果评估:模型到底能不能用4.1 单张图片与批量推理训练完成后,用detect.py做推理验证。单张图片:python detect.py \ --weights runs/train/fire_exp/weights/best.pt \ --source test_images/fire_test.jpg \ --img 640 \ --conf 0.25 \ --project runs/detect \ --name fire_test--conf 0.25是置信度阈值,低于这个值的框会被过滤掉。火焰检测场景下,如果漏检比较严重,可以降到 0.1;如果误检太多,提到 0.5。--source也可以指向一个文件夹,批量推理所有图片,结果会保存在runs/detect/fire_test下,每张图带标注框和类别置信度。批量推理时建议加上--save-txt参数,把检测结果同时输出为 YOLO 格式的 txt,方便后续做定量评估:python detect.py \ --weights runs/train/fire_exp/weights/best.pt \ --source test_images/ \ --conf 0.25 \ --save-txt \ --save-conf--save-conf会在 txt 里额外保存置信度值,格式变成类别 x y w h 置信度。这个文件可以用来和人工标注对比,计算实际部署时的召回率和准确率。4.2 指标解读与误检漏检分析YOLOv5 训练结束后会输出混淆矩阵和 PR 曲线,存放在runs/train/fire_exp下。重点看两个指标:mAP@0.5 和 mAP@0.5:0.95。前者是 IoU 阈值 0.5 时的平均精度,后者是 0.5 到 0.95 多个阈值的平均。火焰检测一般 mAP@0.5 能到 0.85 以上就算可用,如果只有 0.6 左右,说明模型还没学好。误检漏检分析我一般会做两件事:一是把置信度阈值调低到 0.1,看模型在哪些背景上产生了误检,比如夕阳、灯光、红色物体容易被误判为火焰;二是把漏检的图片挑出来,看是不是火焰太小、被遮挡或标注框不准确。如果是小目标漏检,可以在训练时把--img调大,或者在 data.yaml 里开启 mosaic 增强。# 快速统计检测结果中的类别分布 import os from collections import Counter txt_dir = "runs/detect/fire_test/labels" counter = Counter() for fname in os.listdir(txt_dir): with open(os.path.join(txt_dir, fname)) as f: for line in f: cls = int(line.split()[0]) counter[cls] += 1 print("各类别检测框数量:", dict(counter))这段脚本统计推理结果里每个类别的框数量。如果某个类别数量异常少,说明该类别的召回率可能有问题,需要针对性补充训练数据。4.3 模型导出与部署前验证如果要把模型部署到边缘设备或服务端,通常需要导出为 ONNX 或 TensorRT。YOLOv5 提供了export.py:python export.py \ --weights runs/train/fire_exp/weights/best.pt \ --include onnx \ --img 640 \ --batch 1--include支持 onnx、torchscript、engine 等格式。导出 ONNX 后,我一般会用 onnxruntime 跑一遍推理,确认输出和 PyTorch 一致:import onnxruntime as ort import numpy as np sess = ort.InferenceSession("best.onnx") input_name = sess.get_inputs()[0].name # 构造一个模拟输入,实际使用时替换为预处理后的图片 dummy = np.random.randn(1, 3, 640, 640).astype(np.float32) outputs = sess.run(None, {input_name: dummy}) print("ONNX 输出形状:", [o.shape for o in outputs])这一步能提前发现导出时的算子兼容问题,避免部署到一半才发现模型跑不起来。5. 避坑与常见问题排查:那些让我熬夜的坑5.1 训练 loss 不下降或变为 NaN现象:训练启动后 box_loss 一直是 0 或者突然变成 NaN。原因通常是学习率过大、数据标注有非法值、或者 batch 太小导致梯度不稳定。解决:先用第 2 章的脚本检查标签文件,排除坐标越界;然后把--lr0降到 0.001 或 0.0005,--batch至少设为 8。如果还是 NaN,检查 data.yaml 里的 nc 是否和实际类别数一致,不一致会导致分类头维度错误。5.2 推理时检测框位置偏移严重现象:模型能检测到火焰,但框的位置和实际火焰区域对不上,偏上或偏左。原因多半是图片预处理时 resize 和 padding 的方式与训练时不一致。YOLOv5 默认使用 letterbox 填充,保持宽高比。如果你自己写了推理脚本,务必复用 YOLOv5 的datasets.py里的 letterbox 函数,不要直接用 cv2.resize。解决:直接调用utils/augmentations.py里的 letterbox,或者用 detect.py 做推理,避免自己造轮子。5.3 显存不足导致训练中断现象:训练几个 batch 后报 CUDA out of memory。原因:--img或--batch设置过大,或者同时开了多个训练进程。解决:先把 batch 减半,如果还不够就把 img 从 640 降到 416。另外可以在训练命令里加--workers 2减少数据加载进程数,有时 dataloader 的 worker 也会占用显存。如果显卡本身显存小于 6GB,建议直接用 yolov5n 或 yolov5s,别硬上大模型。5.4 验证集 mAP 远低于训练集现象:训练集 loss 很低,但验证集 mAP 只有 0.3 左右。原因:过拟合,或者训练集和验证集分布差异太大。解决:先检查验证集图片是否和训练集来自同一场景,如果验证集全是夜间火焰而训练集全是白天,模型泛化能力肯定差。其次可以增加数据增强,YOLOv5 默认开启了 mosaic、HSV 增强,如果被关掉了要重新打开。最后可以加--dropout 0.2或减小模型规模。5.5 标签文件与图片不匹配现象:训练时警告No labels found或某些图片被跳过。原因:images 和 labels 文件名不一致,或者 labels 目录层级不对。解决:用脚本对比两个目录的文件名集合,找出差集:import os img_dir = "fire_dataset/images/train" lbl_dir = "fire_dataset/labels/train" imgs = {os.path.splitext(f)[0] for f in os.listdir(img_dir)} lbls = {os.path.splitext(f)[0] for f in os.listdir(lbl_dir)} print("有图无标签:", imgs - lbls) print("有标签无图:", lbls - imgs)输出为空才说明完全匹配。如果有差异,手动补齐或删除对应文件。6. 二次开发改造:让火焰检测适配你自己的场景拿到这份数据集和训练好的模型后,真正的工作才刚开始。二次开发最常见的需求是换类别、换场景、换部署平台。我一般会按下面的顺序改造。第一步是扩展类别。如果要在火焰基础上增加烟雾检测,需要重新标注烟雾数据,把 data.yaml 的 nc 改成 2,names 改成['fire', 'smoke'],然后从预训练权重开始微调。注意不要直接改 nc 后加载旧权重,分类头维度不匹配会报错。正确做法是用--weights best.pt加载,YOLOv5 会自动忽略不匹配的分类层并重新初始化。第二步是适配新场景。如果要把模型用到监控摄像头实时视频流,需要把 detect.py 的--source改成 rtsp 地址或摄像头索引,同时把--img降到 416 或 320 保证帧率。我一般会加一个帧跳过逻辑,每三帧检测一次,中间帧复用上一次结果,这样在普通 GPU 上也能跑到 25 FPS 以上。import cv2 import torch model = torch.hub.load('ultralytics/yolov5', 'custom', path='best.pt') cap = cv2.VideoCapture(0) # 换成你的摄像头或视频流地址 frame_count = 0 last_results = None while True: ret, frame = cap.read() if not ret: break frame_count += 1 # 每三帧做一次推理,减少计算量 if frame_count % 3 == 0: results = model(frame, size=416) last_results = results if last_results is not None: # 在原图上画框 annotated = last_results.render()[0] cv2.imshow('fire_detect', annotated) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()这段代码的关键点是frame_count % 3控制推理频率,model(frame, size=416)指定输入尺寸。参数上,size 越小速度越快但精度越低,需要根据你的硬件和场景权衡。如果火焰在画面中占比很小,建议不要降 size,而是用 yolov5s 配合 TensorRT 加速。第三步是模型量化与加速。如果部署到 Jetson 或树莓派,ONNX 模型还可以进一步转 TensorRT 或 OpenVINO。我一般会先用export.py导出 ONNX,再用对应平台的工具转换。转换后务必用同一批测试图片对比 PyTorch 和加速后的输出,确认精度损失在可接受范围内。常见做法是允许 mAP 下降 1 到 2 个百分点,换取 3 到 5 倍的速度提升。第四步是建立持续验证习惯。每次改完数据或模型,我都会跑一遍完整的验证流程:用固定测试集推理、统计 mAP、对比上一次结果。如果 mAP 下降超过 3 个点,就回滚改动。这个习惯帮我避免了好几次“改完感觉更好但实际更差”的翻车。从那以后我每次动数据集或训练参数,都强制走一遍“检查标签 → 小规模训练 → 验证集评估 → 全量训练”的流程,不再凭感觉调参。希望这份火焰数据集和上面的改造思路能帮到你,拿到手先跑通,再按自己的场景一步步改。本文还有配套的精品资源,点击获取
简介:火焰数据集(含标注好的标签)面向从事目标检测的开发者与研究者,尤其适合使用 YOLOv5 训练火焰识别模型的场景,可用于火灾预警、视频监控等实际项目。资源包共 5260 个文件,包含 1853 张 jpg 图像、1853 个 txt 标注文件与 1553 个 xml 标注文件,txt 与 xml 分别对应 YOLO 与 VOC 两种标注格式,便于直接接入不同训练框架,压缩包约 194.03MB。目前已有 4904 人学习下载。数据集覆盖多种光照与场景下的火焰样本,标注信息包含火焰位置、形状与大小,使用 YOLOv5 训练可达到 mAP@.5 为 0.953、mAP@.5:.95 为 0.679 的精度表现。读者可据此完成数据预处理、增强、模型调优与评估的完整流程,并参考指标结果快速验证自己的检测方案,为火焰检测及同类目标检测任务提供可复用的数据基础与训练参考。1. 火焰数据集与 YOLOv5 训练实战:从标注文件到可推理模型如果你正在做火焰检测相关的视觉项目,大概率绕不开两件事:一是找到一份标注质量靠谱的数据集,二是把它塞进 YOLOv5 跑通训练和推理。我最近拿到一份火焰数据集,里面已经包含标注好的标签文件,目录结构是标准的 images/labels 配对形式,标签格式为 YOLO 的 txt 归一化坐标。这意味着不需要自己从零标注,直接就能进入训练环节。这份资源适合两类人:刚接触目标检测、想拿一个真实场景数据集练手的新手,以及需要快速验证火焰检测方案可行性的开发者。下面我会按实际拆项目的顺序,把数据检查、环境搭建、训练配置、推理验证和二次开发改造讲清楚,让你拿到手就能跑,跑完还能改。2. 数据集结构与标注格式:先搞清楚手里有什么2.1 目录组织与文件对应关系拿到数据集后第一件事不是急着写训练脚本,而是把目录结构摸清楚。这份火焰数据集常见做法是分成训练集、验证集,有时还有测试集,每个子集下再分 images 和 labels 两个文件夹。images 里放 jpg 或 png 原图,labels 里放同名的 txt 标注文件。文件名必须一一对应,差一个字符都会导致训练时找不到标签。一个典型的目录长这样:fire_dataset/ ├── images/ │ ├── train/ │ │ ├── fire_0001.jpg │ │ └── fire_0002.jpg │ └── val/ │ ├── fire_0101.jpg │ └── fire_0102.jpg ├── labels/ │ ├── train/ │ │ ├── fire_0001.txt │ │ └── fire_0002.txt │ └── val/ │ ├── fire_0101.txt │ └── fire_0102.txt └── data.yaml这里有个血泪经验:很多人解压后直接把 images 和 labels 平铺在一起,结果 YOLOv5 的 dataloader 按路径拼接时找不到文件。YOLOv5 默认会去 images 路径里把/images/替换成/labels/再找同名 txt,所以目录层级必须严格对应。如果你拿到的数据集结构不同,要么调整目录,要么在 data.yaml 里显式指定路径。2.2 YOLO 标注格式逐字段解读打开任意一个 labels 下的 txt 文件,你会看到类似这样的内容:0 0.512 0.634 0.221 0.318 0 0.734 0.412 0.156 0.287每一行代表一个目标框,五个字段含义分别是:类别索引、中心点 x 归一化坐标、中心点 y 归一化坐标、框宽归一化、框高归一化。归一化是指除以图片宽高,所以数值都在 0 到 1 之间。类别索引从 0 开始,这份火焰数据集如果只有火焰一个类别,那所有行的第一个数字都是 0。这里容易翻车的地方是坐标越界。有些标注工具导出的坐标可能因为图片旋转或裁剪出现大于 1 或小于 0 的值,YOLOv5 训练时虽然会做裁剪,但最好提前检查一遍。我一般会写个脚本扫一遍所有标签文件:import os label_dir = "fire_dataset/labels/train" bad_files = [] for fname in os.listdir(label_dir): if not fname.endswith(".txt"): continue path = os.path.join(label_dir, fname) with open(path, "r") as f: for line_no, line in enumerate(f, 1): parts = line.strip().split() if len(parts) != 5: bad_files.append((fname, line_no, "字段数不对")) continue cls, x, y, w, h = map(float, parts) # 检查归一化坐标是否在合理范围 if not (0 <= x <= 1 and 0 <= y <= 1 and 0 < w <= 1 and 0 < h <= 1): bad_files.append((fname, line_no, f"坐标越界: {x},{y},{w},{h}")) print(f"发现异常文件数: {len(bad_files)}") for item in bad_files[:10]: print(item)这段脚本做三件事:遍历标签目录、检查每行字段数是否为 5、检查归一化坐标是否在合法区间。参数上,label_dir换成你自己的路径即可。如果输出异常文件很多,说明标注质量有问题,需要回到标注环节修复,否则训练出来的模型会出现莫名其妙的漏检。2.3 data.yaml 配置与类别映射YOLOv5 训练依赖一个 data.yaml 文件,里面写明训练集、验证集路径和类别信息。这份火焰数据集通常已经附带,但路径可能需要根据你的实际存放位置调整。一个标准的写法:train: ./fire_dataset/images/train val: ./fire_dataset/images/val nc: 1 names: ['fire']nc是类别数量,names是类别名称列表。如果数据集里除了火焰还有烟雾,那 nc 改成 2,names 写成['fire', 'smoke']。注意 names 的顺序必须和标签文件里的类别索引一致,索引 0 对应 names 第一个元素。我见过有人把顺序写反,训练 loss 正常下降但推理时把烟雾框成火焰,排查半天才发现是这里错了。提示:修改 data.yaml 后,建议用python -c "import yaml; print(yaml.safe_load(open('data.yaml')))"快速验证 YAML 语法,避免缩进错误导致训练启动失败。3. 环境搭建与 YOLOv5 训练:从零跑通第一个 epoch3.1 依赖安装与版本选择YOLOv5 对 PyTorch 和 CUDA 版本比较敏感,版本不匹配会直接报错。我一般会先确认显卡驱动支持的 CUDA 版本,再装对应的 PyTorch。常见做法是用 conda 建一个独立环境,避免污染系统 Python:conda create -n fire_yolo python=3.9 -y conda activate fire_yolo # 根据你的 CUDA 版本选择,这里以 CUDA 11.8 为例 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 克隆 YOLOv5 仓库并安装依赖 git clone https://github.com/ultralytics/yolov5.git cd yolov5 pip install -r requirements.txt参数说明:python=3.9是 YOLOv5 比较稳定的 Python 版本,3.10 以上有时会遇到依赖包不兼容。--index-url指定 PyTorch 官方源,比默认源快很多。如果你没有 GPU,把 cu118 换成 cpu 即可,但训练速度会慢到怀疑人生,火焰数据集这种几百上千张图的规模,CPU 训练可能要跑一整天。安装完成后用一行命令验证环境:python -c "import torch; print(torch.__version__, torch.cuda.is_available())"输出里True表示 GPU 可用。如果显示False,先检查驱动,再检查 PyTorch 版本是否匹配。3.2 训练命令与关键参数调优环境就绪后,把 data.yaml 放到 YOLOv5 根目录,然后启动训练。最基础的命令:python train.py \ --data data.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 100 \ --project runs/train \ --name fire_exp逐参数解释:--data指向你的 data.yaml;--weights指定预训练权重,yolov5s 是最小的模型,速度快适合快速验证,如果精度不够可以换 yolov5m 或 yolov5l;--img 640是输入图片尺寸,火焰数据集如果图片分辨率很高,可以调到 1280,但显存占用会翻倍;--batch 16是批次大小,显存不够就降到 8 或 4;--epochs 100是训练轮数,火焰检测这种单类别任务通常 100 到 300 轮足够收敛;--project和--name决定输出目录。训练过程中终端会打印每个 epoch 的 loss 和 mAP 指标。重点看三个值:box_loss、obj_loss、cls_loss 是否稳定下降,以及 mAP@0.5 是否在上升。如果 loss 震荡剧烈,常见原因是学习率太大或 batch 太小,可以加--lr0 0.001降低初始学习率。如果 mAP 早早卡住不涨,可能是数据量不够或标注质量差,需要回头检查数据集。3.3 训练过程监控与中断恢复YOLOv5 训练时会在runs/train/fire_exp下生成一堆文件,其中results.csv记录了每个 epoch 的详细指标,weights/下保存 best.pt 和 last.pt。我习惯用 TensorBoard 实时看曲线:tensorboard --logdir runs/train浏览器打开对应端口就能看到 loss 和 mAP 曲线。如果训练到一半断电或手动中断,可以用--resume从 last.pt 继续:python train.py --resume runs/train/fire_exp/weights/last.pt这里有个坑:--resume会读取原训练的所有参数,如果你中途改了 data.yaml 或换了数据集,resume 后可能报错或行为异常。稳妥做法是重新开一个实验目录从头训练,别偷懒。注意:训练前务必确认data.yaml里的路径是绝对路径或相对于 YOLOv5 根目录的正确相对路径。路径错误时 YOLOv5 会直接报FileNotFoundError,但有时会静默跳过部分数据,导致训练集实际数量对不上。4. 推理验证与效果评估:模型到底能不能用4.1 单张图片与批量推理训练完成后,用detect.py做推理验证。单张图片:python detect.py \ --weights runs/train/fire_exp/weights/best.pt \ --source test_images/fire_test.jpg \ --img 640 \ --conf 0.25 \ --project runs/detect \ --name fire_test--conf 0.25是置信度阈值,低于这个值的框会被过滤掉。火焰检测场景下,如果漏检比较严重,可以降到 0.1;如果误检太多,提到 0.5。--source也可以指向一个文件夹,批量推理所有图片,结果会保存在runs/detect/fire_test下,每张图带标注框和类别置信度。批量推理时建议加上--save-txt参数,把检测结果同时输出为 YOLO 格式的 txt,方便后续做定量评估:python detect.py \ --weights runs/train/fire_exp/weights/best.pt \ --source test_images/ \ --conf 0.25 \ --save-txt \ --save-conf--save-conf会在 txt 里额外保存置信度值,格式变成类别 x y w h 置信度。这个文件可以用来和人工标注对比,计算实际部署时的召回率和准确率。4.2 指标解读与误检漏检分析YOLOv5 训练结束后会输出混淆矩阵和 PR 曲线,存放在runs/train/fire_exp下。重点看两个指标:mAP@0.5 和 mAP@0.5:0.95。前者是 IoU 阈值 0.5 时的平均精度,后者是 0.5 到 0.95 多个阈值的平均。火焰检测一般 mAP@0.5 能到 0.85 以上就算可用,如果只有 0.6 左右,说明模型还没学好。误检漏检分析我一般会做两件事:一是把置信度阈值调低到 0.1,看模型在哪些背景上产生了误检,比如夕阳、灯光、红色物体容易被误判为火焰;二是把漏检的图片挑出来,看是不是火焰太小、被遮挡或标注框不准确。如果是小目标漏检,可以在训练时把--img调大,或者在 data.yaml 里开启 mosaic 增强。# 快速统计检测结果中的类别分布 import os from collections import Counter txt_dir = "runs/detect/fire_test/labels" counter = Counter() for fname in os.listdir(txt_dir): with open(os.path.join(txt_dir, fname)) as f: for line in f: cls = int(line.split()[0]) counter[cls] += 1 print("各类别检测框数量:", dict(counter))这段脚本统计推理结果里每个类别的框数量。如果某个类别数量异常少,说明该类别的召回率可能有问题,需要针对性补充训练数据。4.3 模型导出与部署前验证如果要把模型部署到边缘设备或服务端,通常需要导出为 ONNX 或 TensorRT。YOLOv5 提供了export.py:python export.py \ --weights runs/train/fire_exp/weights/best.pt \ --include onnx \ --img 640 \ --batch 1--include支持 onnx、torchscript、engine 等格式。导出 ONNX 后,我一般会用 onnxruntime 跑一遍推理,确认输出和 PyTorch 一致:import onnxruntime as ort import numpy as np sess = ort.InferenceSession("best.onnx") input_name = sess.get_inputs()[0].name # 构造一个模拟输入,实际使用时替换为预处理后的图片 dummy = np.random.randn(1, 3, 640, 640).astype(np.float32) outputs = sess.run(None, {input_name: dummy}) print("ONNX 输出形状:", [o.shape for o in outputs])这一步能提前发现导出时的算子兼容问题,避免部署到一半才发现模型跑不起来。5. 避坑与常见问题排查:那些让我熬夜的坑5.1 训练 loss 不下降或变为 NaN现象:训练启动后 box_loss 一直是 0 或者突然变成 NaN。原因通常是学习率过大、数据标注有非法值、或者 batch 太小导致梯度不稳定。解决:先用第 2 章的脚本检查标签文件,排除坐标越界;然后把--lr0降到 0.001 或 0.0005,--batch至少设为 8。如果还是 NaN,检查 data.yaml 里的 nc 是否和实际类别数一致,不一致会导致分类头维度错误。5.2 推理时检测框位置偏移严重现象:模型能检测到火焰,但框的位置和实际火焰区域对不上,偏上或偏左。原因多半是图片预处理时 resize 和 padding 的方式与训练时不一致。YOLOv5 默认使用 letterbox 填充,保持宽高比。如果你自己写了推理脚本,务必复用 YOLOv5 的datasets.py里的 letterbox 函数,不要直接用 cv2.resize。解决:直接调用utils/augmentations.py里的 letterbox,或者用 detect.py 做推理,避免自己造轮子。5.3 显存不足导致训练中断现象:训练几个 batch 后报 CUDA out of memory。原因:--img或--batch设置过大,或者同时开了多个训练进程。解决:先把 batch 减半,如果还不够就把 img 从 640 降到 416。另外可以在训练命令里加--workers 2减少数据加载进程数,有时 dataloader 的 worker 也会占用显存。如果显卡本身显存小于 6GB,建议直接用 yolov5n 或 yolov5s,别硬上大模型。5.4 验证集 mAP 远低于训练集现象:训练集 loss 很低,但验证集 mAP 只有 0.3 左右。原因:过拟合,或者训练集和验证集分布差异太大。解决:先检查验证集图片是否和训练集来自同一场景,如果验证集全是夜间火焰而训练集全是白天,模型泛化能力肯定差。其次可以增加数据增强,YOLOv5 默认开启了 mosaic、HSV 增强,如果被关掉了要重新打开。最后可以加--dropout 0.2或减小模型规模。5.5 标签文件与图片不匹配现象:训练时警告No labels found或某些图片被跳过。原因:images 和 labels 文件名不一致,或者 labels 目录层级不对。解决:用脚本对比两个目录的文件名集合,找出差集:import os img_dir = "fire_dataset/images/train" lbl_dir = "fire_dataset/labels/train" imgs = {os.path.splitext(f)[0] for f in os.listdir(img_dir)} lbls = {os.path.splitext(f)[0] for f in os.listdir(lbl_dir)} print("有图无标签:", imgs - lbls) print("有标签无图:", lbls - imgs)输出为空才说明完全匹配。如果有差异,手动补齐或删除对应文件。6. 二次开发改造:让火焰检测适配你自己的场景拿到这份数据集和训练好的模型后,真正的工作才刚开始。二次开发最常见的需求是换类别、换场景、换部署平台。我一般会按下面的顺序改造。第一步是扩展类别。如果要在火焰基础上增加烟雾检测,需要重新标注烟雾数据,把 data.yaml 的 nc 改成 2,names 改成['fire', 'smoke'],然后从预训练权重开始微调。注意不要直接改 nc 后加载旧权重,分类头维度不匹配会报错。正确做法是用--weights best.pt加载,YOLOv5 会自动忽略不匹配的分类层并重新初始化。第二步是适配新场景。如果要把模型用到监控摄像头实时视频流,需要把 detect.py 的--source改成 rtsp 地址或摄像头索引,同时把--img降到 416 或 320 保证帧率。我一般会加一个帧跳过逻辑,每三帧检测一次,中间帧复用上一次结果,这样在普通 GPU 上也能跑到 25 FPS 以上。import cv2 import torch model = torch.hub.load('ultralytics/yolov5', 'custom', path='best.pt') cap = cv2.VideoCapture(0) # 换成你的摄像头或视频流地址 frame_count = 0 last_results = None while True: ret, frame = cap.read() if not ret: break frame_count += 1 # 每三帧做一次推理,减少计算量 if frame_count % 3 == 0: results = model(frame, size=416) last_results = results if last_results is not None: # 在原图上画框 annotated = last_results.render()[0] cv2.imshow('fire_detect', annotated) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()这段代码的关键点是frame_count % 3控制推理频率,model(frame, size=416)指定输入尺寸。参数上,size 越小速度越快但精度越低,需要根据你的硬件和场景权衡。如果火焰在画面中占比很小,建议不要降 size,而是用 yolov5s 配合 TensorRT 加速。第三步是模型量化与加速。如果部署到 Jetson 或树莓派,ONNX 模型还可以进一步转 TensorRT 或 OpenVINO。我一般会先用export.py导出 ONNX,再用对应平台的工具转换。转换后务必用同一批测试图片对比 PyTorch 和加速后的输出,确认精度损失在可接受范围内。常见做法是允许 mAP 下降 1 到 2 个百分点,换取 3 到 5 倍的速度提升。第四步是建立持续验证习惯。每次改完数据或模型,我都会跑一遍完整的验证流程:用固定测试集推理、统计 mAP、对比上一次结果。如果 mAP 下降超过 3 个点,就回滚改动。这个习惯帮我避免了好几次“改完感觉更好但实际更差”的翻车。从那以后我每次动数据集或训练参数,都强制走一遍“检查标签 → 小规模训练 → 验证集评估 → 全量训练”的流程,不再凭感觉调参。希望这份火焰数据集和上面的改造思路能帮到你,拿到手先跑通,再按自己的场景一步步改。本文还有配套的精品资源,点击获取