简介:面向火灾监测、安防巡检等场景的YOLOv7火焰与烟雾检测完整方案,提供训练好的PyTorch权重、Python推理/训练代码,以及1000张已标注图片,标签格式包含XML和TXT两种,类别为fire和smoke。压缩包共188个文件,体积659.06MB,除核心pt权重、py脚本和jpg样本外,还包含yaml配置文件、ipynb示例、events训练日志、Dockerfile等,便于复现环境与二次开发。内容预览中可见多种导出部署示例,如ONNXRuntime与TensorRT动态批次脚本,以及精度对比实验,适合希望快速落地检测或深入理解YOLOv7训练流程的开发者。已有744人学习下载,是平衡“开箱即用”与“源码可读”的实操型资源,能省去自行标注和调参的大量时间。
1. YOLOv7火焰和烟雾检测:为什么说你拿到的是一套“半成品”方案
先给你一句结论:标题里的“YOLOv7火焰和烟雾检测+训练好的权重+1000标注好的数据集”,翻译成落地语言就是——你已经绕过了最耗时的数据采集和模型训练阶段,拿到的是一个可以直接做推理验证、甚至直接进生产的检测方案。很多人第一次接触这个标题时以为还需要自己从头训练,其实不是,权重和数据集都齐了,你要做的事是从推理开始,而不是从标注开始。
这套组合解决的是场景监控里的一个非常具体的需求:在工厂车间、山林卡口、小区地库、仓库走廊里,用一台普通摄像头实时发现火焰和烟雾。它的价值在于,把“要不要装烟雾传感器”这种硬件问题变成了“用现有摄像头能不能识别”的软件问题。适合谁?适合有摄像头但不想额外布传感器的运维工程师、做安防集成的交付人员,以及刚接触目标检测但手里没有现成数据的学生开发者。
但要提醒一点:1000张标注图属于“能训练出可用模型、但离完美很远”的数据规模。它能覆盖常见室内外场景,对距离近、目标大、对比明显的火焰烟雾效果不错,可一旦遇到逆光、夜间、极小目标,就很容易翻车。这篇文章我不会只告诉你“怎么跑通”,而是会把检测模块、权重验证、参数调优、部署适配和踩坑记录完整拆开,让你拿到这套资源后能判断它到底适不适合你的现场。
2. 检测模块解析:YOLOv7做火焰烟雾识别的原理与最小可用代码
2.1 为什么火焰烟雾检测要选YOLOv7而不是其他版本
YOLOv7在2022年发布时主打的就是“实时性+高精度”的平衡,这个平衡对火焰烟雾场景特别重要。火焰和烟雾没有固定的形状,边缘模糊、透明度高、颜色跨度大(从橙红到灰白都有),这些特性决定了检测模型必须同时具备较强的特征提取能力和较快的推理速度,YOLOv7正好卡在这个交叉点上。相比更早的YOLOv5,YOLOv7引入了可重参数化卷积和辅助训练头,在不明显增加推理时间的前提下提升了小目标召回率;相比后来的YOLOv8,YOLOv7的部署生态更成熟,很多边缘设备厂商的SDK都优先适配它。
另外,这个标题给出的是“训练好的权重”,意味着模型已经收敛过一轮。你接手后的主要工作不是调训练参数,而是理解这个权重在什么条件下表现好、在什么条件下会漏报误报。有一个很关键的机制你需要先懂:YOLOv7的输出层会生成三个不同尺度的预测结果,分别负责大、中、小目标。火焰烟雾恰恰是“尺度跨度极大”的目标——近处一团火可能是大目标,远处一缕烟可能只有几个像素。所以你在调参时最需要关注的不是模型结构,而是置信度阈值和NMS阈值的配合。
2.2 本地跑通推理的最小代码:从加载权重到输出检测框
我一般会建议先跑一张静态图片验证整套环境,再切到视频流。下面是加载训练好的权重做单图推理的最小代码,用你拿到的best.pt即可:
import cv2 import torch from models.experimental import attempt_load from utils.general import non_max_suppression, scale_coords from utils.augmentations import letterbox # 加载模型,map_location='cpu' 保证没有GPU时也能跑 model = attempt_load('weights/best.pt', map_location='cpu') model.eval() # 读取并预处理图片 img0 = cv2.imread('test_fire.jpg') img = letterbox(img0, new_shape=640, stride=32)[0] img = img[:, :, ::-1].transpose(2, 0, 1) # BGR转RGB并调整维度 img = torch.from_numpy(img.copy()).float() / 255.0 img = img.unsqueeze(0) # 推理 + NMS with torch.no_grad(): pred = model(img)[0] pred = non_max_suppression(pred, conf_thres=0.25, iou_thres=0.45) # 将预测框坐标还原到原图尺寸并绘制 for det in pred: if len(det): det[:, :4] = scale_coords(img.shape[2:], det[:, :4], img0.shape).round() for *xyxy, conf, cls in det: label = f'fire' if int(cls) == 0 else f'smoke' cv2.rectangle(img0, (int(xyxy[0]), int(xyxy[1])), (int(xyxy[2]), int(xyxy[3])), (0, 0, 255), 2) cv2.putText(img0, f'{label} {conf:.2f}', (int(xyxy[0]), int(xyxy[1])-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2) cv2.imwrite('result.jpg', img0)代码逻辑不复杂:attempt_load读取训练权重,letterbox把输入图缩放到640×640同时保持宽高比,避免目标变形影响检测精度;non_max_suppression做类别筛选和重叠框抑制。这里的两个阈值值得你专门调:conf_thres控制“多高的置信度才算检出”,iou_thres控制“两个重叠框是否合并为一个”。
参数说明要记住一条经验:烟雾目标通常比火焰更难检,因为烟雾边缘灰度值与背景差异小。如果你发现火焰能检出来但烟雾漏检,把conf_thres从0.25降到0.15,烟雾检出率会明显上升,代价是误报也会增加,比如把云、蒸汽、灰尘当成烟雾。实际使用时我一般会设成0.2,配合后续的帧间确认逻辑来抵消误报。
2.3 两类目标的检测差异:火焰易检烟雾难,参数要分开理解
火焰和烟雾在检测难度上完全不是一个量级,这是这套权重和数据集最需要你心里有数的地方。火焰的核心特征是高亮度和橙红色调,在YOLOv7的特征空间里这种颜色对比非常强烈,学习起来很容易,所以火焰的置信度普遍在0.7以上。烟雾则不同,它是半透明的、缓慢扩散的、颜色接近灰白或蓝灰,和天空、墙面、水蒸气的特征高度相似,模型只能靠纹理和边缘形态来区分,置信度往往只有0.3到0.5。
明白这个差异后,你在做检测阈值时就不能用一个固定值。我的做法是写一个类别感知阈值:火焰用0.35,烟雾用0.2,效果比统一用0.25好很多。另外一个值得注意的现象是,烟雾通常出现在火焰上方或者周围,如果你看到检测结果里同一个区域频繁出现“fire”和“smoke”两个框交替,那不是模型错了,而是烟雾浓度在变化导致置信度在临界值附近抖动。这种时候不要调阈值去压,应该靠后续的连续帧逻辑去平滑。
至于NMS阈值iou_thres,火焰烟雾场景里我建议保持0.45不变,不需要动。原因是大火场景中火焰区域本身会碎裂成多个小框,如果把IOU阈值调得太低(比如0.3),这些碎裂的小框会被合并,导致整体框偏小、覆盖不全;维持0.45左右既允许同一个火焰区域有多个框叠加,又能抑制独立目标之间的误合并。
3. 权重与数据集的验收:在盲目信任之前先做这三步确认
3.1 第一步:检查权重文件与模型结构的匹配度
拿到“训练好的权重”后第一件事不是跑图片,而是确认这个权重和你的YOLOv7代码版本对得上。YOLOv7有两个容易混淆的配置:标准版(yolov7.pt)和E端高效版(yolov7-e6.pt),它们的网络深度和宽度不同,权重文件的张量形状也不同。如果你用标准版的models/yolov7.yaml去加载一个从E端训练出的权重,会直接报结构不匹配的错误。
检查方法很简单,加载权重后看一眼模型输出的类别数是不是2:
import torch # 加载权重并检查类别数 ckpt = torch.load('weights/best.pt', map_location='cpu') num_classes = ckpt['model'].hyp['nc'] if 'model' in ckpt else None # 如果类别数不是2,说明这份权重可能不是火焰+烟雾两个类别 print(f'类别数: {num_classes}') # 常见错误:权重文件虽然是.pt,但内部结构被改动过 if num_classes != 2: print('警告:类别数不是2,请确认这份权重对应的训练配置')这段代码能在5秒内暴露80%以上的权重不匹配问题。常见的异常情况包括:权重是某个火灾数据集训练的、但只含“fire”一个类别;或者训练时用了3个类别(fire、smoke、person),但你的推理代码只处理了前两个。这两种情况到部署时都会导致类别索引错乱——你画出来的“fire”框里可能是人。
另一个需要确认的是权重文件的完整性。有些渠道下载的best.pt只有几百KB,这种多半是断点下载不完整或者源码包里的占位文件。真正训练完的YOLOv7权重(640分辨率、2个类别)至少在25MB以上,如果拿到的是小文件,建议直接找获取渠道重新要,不要浪费时间在加载调试上。
3.2 第二步:用评估脚本量化mAP,不要靠肉眼判断好坏
很多人在验证权重时习惯找几张图看看“能不能检出”,这种做法完全不够。因为火焰烟雾这种目标在单张图上检出不算本事,关键要看整体召回率和误报率。我会用YOLOv7自带的test.py脚本跑一遍验证集,核心看三个指标。
python test.py --data data/fire_smoke.yaml --weights weights/best.pt --batch-size 8 --conf-thres 0.25 --iou-thres 0.5 --task val跑完会输出P、R、mAP@.5、mAP@.5:.95四组核心指标。对火焰烟雾这个场景按经验值判断:mAP@.5应该大于0.75才算合格,如果低于0.6,说明这份权重对验证集的覆盖能力很弱,部署到现场大概率会频繁漏报。但光看mAP还不够,你还要看每一类单独的AP。常见的情况是fire类的AP在0.85以上,smoke类只有0.55,这种“偏科”模型到现场后烟雾基本是摆设。
看指标时有一个容易误解的地方:mAP@.5:.95这个值通常比mAP@.5低很多,这不代表模型差。因为:.95的评估标准要求预测框与真实框的IOU达到0.95才算完全正确,火焰烟雾这种边界不清晰的目标天然很难达到高IOU。你真正应该关心的是mAP@.5这个基础指标,以及PR曲线在低置信度区间是否出现急剧下降。如果PR曲线尾部掉得很陡,说明模型存在大量低置信度误检,后期用阈值压不掉。
3.3 第三步:在自建验证集上做边界行为测试
验证集指标再高,到了实际现场也未必可靠,因为训练数据和你现场的镜头角度、光照条件、背景纹理大概率不一样。我会有一个固定的“自定义验证集”动作:从实际监控里抽3到5段视频,每段截取大约50帧包含火焰或烟雾的画面,再和标签对比,看检出率和误报率会不会发生明显变化。
具体的跑法是把视频帧一帧一帧地喂给模型,保存每帧的检测结果,最后统计两个数字:检出率(实际有火有烟的画面中被标记出来的比例)和误报率(没有火烟但被标记出来的比例)。
import cv2 import torch model = torch.hub.load('path/to/yolov7', 'custom', 'weights/best.pt', source='local') cap = cv2.VideoCapture('field_video.mp4') total_frames = 0 true_positive = 0 false_positive = 0 while True: ret, frame = cap.read() if not ret: break total_frames += 1 results = model(frame, size=640) dets = results.pandas().xyxy[0] # 这里假设你已经人工标注出了哪些帧真有火焰烟雾 has_fire_ground_truth = check_ground_truth(total_frames) has_detection = len(dets) > 0 if has_fire_ground_truth and has_detection: true_positive += 1 elif not has_fire_ground_truth and has_detection: false_positive += 1 cap.release() print(f'检出率: {true_positive / total_frames:.2f}')这个自建验证不需要你写复杂的评估逻辑,只需要在跑之前建立“每帧是否有真实火焰烟雾”的标记,哪怕用视频剪辑软件粗略切分就行。重点是看两类曲线:一类是烟雾从淡到浓的过程,模型在哪一帧开始“认出”烟雾;另一类是逆光或夜间场景,模型是否出现大面积误报。这两个边界行为决定了你部署后需不需要加额外的条件过滤。
4. 五种部署形态的推理适配:摄像头、视频、RTSP流与边缘设备
4.1 摄像头实时检测的代码框架:帧率与检测速度的取舍
从静态图片过渡到实时视频,最核心的变化是帧率。桌面级GPU跑YOLOv7的640输入大约是30到60FPS,但实际部署现场的摄像头往往只有15到25FPS,所以模型速度通常不是瓶颈,瓶颈在解码和预处理。你需要做的一件事是保证“检测不丢帧”——宁可降低检测频率,也不要让处理管线积压。
我常用的做法是跳帧检测:每3帧做一次推理,中间两帧直接复制上一帧的检测结果。这在火焰烟雾场景里完全可行,因为火焰和烟雾的变化是渐变式的,除非是爆燃那种瞬间变化,否则跳帧不会造成明显漏检。下面是摄像头实时检测的完整框架:
import cv2 import torch # 加载模型 model = torch.hub.load('path/to/yolov7', 'custom', 'weights/best.pt', source='local') cap = cv2.VideoCapture(0) # 或摄像头RTSP地址 frame_count = 0 last_results = None while True: ret, frame = cap.read() if not ret: break frame_count += 1 # 每3帧推理一次,中间帧复用上一次结果,降低CPU/GPU占用 if frame_count % 3 == 0: results = model(frame, size=640) last_results = results elif last_results is not None: results = last_results # 绘制检测框并输出 if last_results is not None: dets = results.pandas().xyxy[0] for _, row in dets.iterrows(): x1, y1, x2, y2 = int(row['xmin']), int(row['ymin']), int(row['xmax']), int(row['ymax']) label = f"{row['name']} {row['confidence']:.2f}" color = (0, 0, 255) if row['name'] == 'fire' else (128, 128, 128) cv2.rectangle(frame, (x1, y1), (x2, y2), color, 2) cv2.putText(frame, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2) cv2.imshow('Fire/Smoke Detection', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()这个框架有两个值得说的参数。第一个是frame_count % 3的跳帧间隔,如果现场火焰烟雾变化速度较快(比如化工厂气体泄漏后迅速燃烧),建议改成每2帧推理一次;如果是山林监控这种缓慢场景,每5帧推理一次也够用。第二个是size=640,如果你用的是边缘设备或核显,可以降到416,速度能提升一倍以上,但小目标的检出率会下降,需要你在部署前用自建验证集测一遍。
4.2 视频文件离线推理:批量处理时的内存管理与输出封装
很多场景不是实时检测,而是事后对历史监控录像做分析。比如工厂火灾调查、森林防火的录像复盘,这些场景下你更关心的是“能不能把全程视频里所有出现火焰烟雾的片段切出来”,而不是实时报警。离线处理时会遇到一个实时检测没有的麻烦:视频很长、帧数很多,如果每一帧都保存检测结果,内存会被撑爆。
我的做法是只保存两类信息:检测到目标的帧号和该帧的检测框信息,视频帧本身不保存,需要时再回原视频重新截取。另一个问题是长时间视频的置信度波动——模型的置信度会随画面内容变化而抖动,同一个火焰区域在某些帧是0.5、某些帧是0.2,如果你用固定阈值来判断“是否检出”,会把火焰分割成一段一段的检出区间。
import cv2 from collections import deque # 用队列保存最近5帧的检测结果,做时间维度的平滑确认 detection_history = deque(maxlen=5) stable_fire = False cap = cv2.VideoCapture('warehouse_recording.mp4') fps = cap.get(cv2.CAP_PROP_FPS) frame_idx = 0 fire_segments = [] while True: ret, frame = cap.read() if not ret: break frame_idx += 1 results = model(frame, size=640) has_fire = any(r['name'] == 'fire' for r in results.pandas().xyxy[0].to_dict('records')) detection_history.append(has_fire) # 连续3帧以上检出才算稳定目标,避免单帧误检 if sum(detection_history) >= 3 and not stable_fire: stable_fire = True fire_segments.append({'start_frame': frame_idx}) elif sum(detection_history) < 2 and stable_fire: stable_fire = False fire_segments[-1]['end_frame'] = frame_idx cap.release()这段代码里的帧历史队列是离线分析的关键。火焰烟雾检出不像人脸识别那样可以单帧断定,它需要连续几帧都检出才能确认不是误报。maxlen=5表示只记最近5帧,连续3帧检出才确认目标开始,连续2帧不检出就确认目标结束。这个参数的效果是消除了大量单帧误报,代价是短的火焰闪烁(少于3帧)会被忽略,但这在监控场景里通常不是问题。
4.3 RTSP流接入与断线重连机制:稳定性的三个关键点
把检测程序接到现场摄像头的RTSP流,是部署到真实环境必须过的一关。RTSP流有两个很烦的问题:网络抖动导致丢帧,以及摄像头断线后程序直接崩溃。前者会让检测结果出现过场式的漏检,后者需要手动重启程序,在无人值守的机房是不可接受的。
解决断线崩溃的核心是给VideoCapture加重连逻辑。我见过很多人在这个地方翻车:cap.read()返回False时不做处理,程序跑一会儿就异常退出。但要特别注意,OpenCV的VideoCapture在RTSP流断开后即使重连也可能失败,需要重新创建捕获对象。
import cv2 import time rtsp_url = "rtsp://your_camera_ip:554/stream1" cap = None def create_capture(url): cap = cv2.VideoCapture(url) cap.set(cv2.CAP_PROP_BUFFERSIZE, 3) # 减小缓冲区,降低延迟 return cap while True: if cap is None: cap = create_capture(rtsp_url) ret, frame = cap.read() if not ret: print("帧读取失败,尝试重连...") cap.release() cap = None time.sleep(3) # 等3秒再重连,避免频繁请求 continue # 正常检测逻辑 results = model(frame, size=640) time.sleep(0.03)重连机制的三个关键点:CAP_PROP_BUFFERSIZE要调小,默认值在某些摄像头SDK下会积累十几帧的延迟,火焰报警晚几秒可能就是火势蔓延的事;time.sleep(3)的重连间隔不能太短,否则摄像头还在重启过程中会形成连接风暴;重连后第一帧检测结果要丢弃,因为刚连上时的画面可能是花屏或上一个连接残留。这些细节决定你的程序能不能在无人值守环境下跑一周不出问题。
4.4 边缘设备部署:TensorRT加速与INT8量化对精度的影响
如果现场只提供了边缘盒子(比如某公司的NVR一体机或嵌入式GPU平台),你需要在推理框架上做适配。常见做法是用TensorRT把PyTorch权重转成engine格式,推理速度能提升2到4倍,但火焰烟雾检测有个特殊问题:INT8量化对烟雾类目标的精度损伤特别明显。
原因是烟雾的特征纹理细腻,INT8量化把特征的数值精度从FP16压到INT8,烟雾边缘的微弱纹理信息会被截断,导致模型对烟雾的置信度整体降低。我做过对比实验,FP16推理时烟雾的mAP是0.62,INT8之后降到0.48,火焰反而只降了0.03。所以如果你需要在边缘设备上部署,优先用FP16而不是INT8;只有当设备显存实在不够时才考虑INT8,并且要针对烟雾类单独加大训练数据中的纹理多样性。
# 将best.pt转为TensorRT FP16 engine python export.py --weights weights/best.pt --include engine --device 0 --half # 验证转换后的engine在烟雾场景的检出效果 python detect.py --weights weights/best.engine --source test_video.mp4 --conf-thres 0.2转换后的engine文件与你的GPU型号强绑定,换一块不同型号的显卡就要重新转换。还有一个容易忽略的事项:TensorRT转换时需要消耗显存做校准和优化,如果显卡本身在跑推理,转换时会因为显存不足而失败。建议转换前先停掉推理服务,或者用命令行加--workspace 2限制显存占用。
5. 避坑清单:权重、数据集与部署中反复出现的五个问题
5.1 训练好的权重视觉上有效但评估指标很差
现象:拿几张现场截图测试,火焰和烟雾都能画框,感觉模型“还行”,但跑test.py评估时mAP只有0.5左右,远低于预期。
原因:单张图片的“成功检出”可能是模型用高置信度记住了训练集里的某些特征,比如图片色调偏暖、背景是特定的仓库颜色。评估指标差说明模型在验证集上的泛化能力不足,本质上训练集多样性不够。1000张图对火焰烟雾这种形态变化极大的目标来说偏少。
解决:不要被单张效果迷惑,一定要跑完整评估。如果评估确实差,优先扩充训练数据,而不是继续调推理参数。一个可行的路径是把自己拍到的视频帧加入训练集,用现有权重做半自动标注(伪标签),人工修正后再训练一轮。
5.2 smoke类的置信度普遍偏低且与fire混淆
现象:烟雾的检出置信度集中在0.15到0.3之间,而且频繁被标成fire;带蒸汽的工业管道也被检出为smoke。
原因:烟雾样本在1000张训练图里占比可能偏低,模型对烟雾特征的记忆不充分。另外烟雾与蒸汽在灰度纹理上高度相似,数据如果没有覆盖足够多的“蒸汽反例”,模型天然会混淆。
解决:两件事并行。一是在推理时代码里做成类别感知阈值,smoke用0.15,fire用0.35;二是在数据层面补充负样本,尤其是工厂蒸汽、冷天呼气、烧水壶蒸汽这些容易误报的画面,各收集几十张不标注直接加入训练集,让模型学会区分烟雾和蒸汽。
5.3 夜间和逆光场景大面积漏检
现象:白天效果还可以,到了夜间或强逆光时,模型几乎检测不到火焰烟雾,有时候连明显的火焰都漏了。
原因:训练数据大概率没有覆盖夜间的红外成像特征。火焰在夜间监控中的形态是亮斑加光晕,烟雾在红外下几乎是透明的,与日光下的RGB特征完全不同,模型没见过这种数据,表现自然崩塌。
解决:夜间部署必须单独采集夜间数据重新训练。如果暂时没有夜间标注数据,一个不算优雅但有效的兜底方案是叠加帧差法——对相邻两帧做差分,火焰的闪烁特性和烟雾的缓慢扩散会造成明显的帧间差异区域,再配合模型在该区域的检测结果做确认,能挽回一部分漏检。但这不是长久之计,最终还得靠夜间数据。
5.4 数据集标注质量有问题:边界框画得过大导致模型学习到错误特征
现象:模型检出的火焰框总是比实际火焰大一圈,而且置信度虚高,但换一个场景后置信度骤降。
原因:原始1000张数据的标注框可能包含了火焰周围的烟雾区域,模型学到的是“火焰等于一个包含橙色和灰色的椭圆区域”。当遇到只有火焰没有被烟雾包裹的现场时,特征不匹配导致置信度下降。
解决:翻查标注文件,重点看fire类别的边界框是否紧贴火焰轮廓。YOLO格式的标注是归一化的x_center y_center width height,如果width和height明显偏大(比如火焰实际宽度占图5%,标注框却有10%),需要手动修正或用标注工具重新调整。这一步工作量大,但对模型精度的提升最明显。
5.5 数据集类别不平衡:smoke只有fire样本量的三分之一
现象:训练出的模型在测试集上fire的AP是0.85,smoke的AP只有0.4,整体mAP被smoke拖累。
原因:这是1000张数据集最常见的问题,火焰目标显眼容易标注,收集者也更关注火焰;烟雾数据要么占比少,要么只在“有火焰”的图片里出现,导致模型对纯烟雾场景(比如阴燃初期)经验不足。
解决:先确认数据分布。如果smoke样本确实太少,有两种路径:一种是用数据增强策略,对已有的smoke样本做随机裁剪、旋转、颜色抖动,把有效样本量放大;另一种是收集更多纯烟雾场景的真实图片,包括厨房油烟、火灾初期阴燃、远处山林薄雾。前者能短时间提升指标,后者才是根治。
6. 进阶:把预训练权重变成你自己场景的专用模型
当你把前五章的内容都走通之后,手里的权重已经能跑了,但它还是“通用模型”,不是“你的现场模型”。一个工厂的火焰烟雾和一片山林的火焰烟雾在形态上差异巨大:工厂里多为管道喷射火和油类火焰,颜色偏黄白;山林里多是树冠火,颜色偏橙红且伴随大量黑烟。通用权重很难同时覆盖这两种场景。
这时的进阶操作是增量微调,也叫“迁移学习二段训练”。做法是在现有权重的基础上,用你自采的几百张现场图片继续训练,而不是从头训练。YOLOv7源码支持这个操作,你只需要修改数据配置文件,把预训练权重路径指向已有的best.pt即可。这里的关键是训练参数要克制——已经收敛的模型再次训练,学习率如果还是从头训练的0.01,会把之前学到的通用特征冲刷掉,一般建议用0.0005以下的学习率,训练50到100轮就够了。
python train.py --weights weights/best.pt --data your_data.yaml --hyp data/hyp.scratch.custom.yaml --epochs 80 --batch-size 16 --img 640 --device 0增量训练结束后,在自建验证集上重新评估。如果你的现场数据与原始训练集差异较大,你会看到fire或smoke的AP比原始权重下降了一些,这是正常的,因为模型在“遗忘”通用的火焰特征来适应你的现场;但如果两个类的AP同时大幅下降,说明你的新训练集太单一,模型过拟合了。解决办法是切分训练集时保留20%的原始数据混入一起训练。
最终的部署习惯上,我倾向于用两段式策略:先用增量微调后的权重做主力推理,同时保留原始权重做影子模式——也就是在后台跑一遍,对比两者的检测差异。这样做一到两周,你就能统计出新权重在你的现场到底改进了多少漏报和误报。我自己有过一次教训,某次做仓库监控项目时没有保留影子模式就直接换上了增量权重,结果夜间红外场景误报暴涨两倍,花了三天才排查出来是增量训练数据里混入了几条阴影样本。从那以后我每次微调权重都保留旧权重做对比,再没翻过车。希望这些经验能帮到你。
本文还有配套的精品资源,点击获取