ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

输电线路金具检测:YOLO数据集制作与训练全流程指南

输电线路金具检测:YOLO数据集制作与训练全流程指南 简介这是一份面向YOLO目标检测实战的输电线路电力金具检测数据集适用于电力巡检、工业视觉检测相关的研究人员与工程技术人员。数据集基于真实场景拍摄包含一千张图片对应的VOCXML、COCOJSON和YOLOTXT三种格式标签分别存放于独立文件夹可直接用于YOLO系列模型的训练与评估。资源包共两千个文件以一千个XML标注文件和九百九十个TXT标签文件为主体另有六个HTML教程、三个Python划分脚本及一个YAML配置文件整体约一百四十一点九七兆字节。目前已有五百五十二人学习并下载使用。配套内容包含YOLO环境搭建与训练案例教程区分Windows、Linux版本和划分脚本可灵活重组数据、快速验证模型另附数据集详情展示链接并支持私信获取更多数量或其他数据集。1. 输电线路金具检测一套数据包能带你把YOLO训练完整跑通搞电力巡检目标检测的人多半都卡在同一个环节不是算法选型没思路而是手里没有像样的标注数据。网上公开的输电线路数据集极少绝缘子、防震锤、均压环这些金具类别能凑齐一千张带标签图片已经算很可用的起步盘。标题这套“YOLO输电线路电力金具检测数据集”把1000张图片、VOC/COCO/YOLO三种格式的标签、划分脚本和训练教程打包在一起本质上解决的是两件事一是省掉你从头标注和格式转换的脏活二是给你一条从文件解压到模型跑通的完整路径。适合正在做电力巡检算法验证的工程师、拿目标检测做毕业设计的学生以及想快速评估金具检测可行性的团队。这套东西的用法有正确顺序先检查、再转换、后划分、最后训练按这个链路走能少踩一半的坑。2. 拆解数据集VOC/COCO/YOLO三种标签格式到底好在哪拿到压缩包第一步不是解压了直接开训而是先看清目录结构和标签格式。这个数据集同时提供三种格式是因为不同训练框架和脚本对标注的读取方式完全不同YOLO系列原生的txt标签格式读取最快Detectron2和MMDetection更习惯COCO的json而VOC的xml则保留了一部分目标属性信息。三种格式全给意味着你换框架时不用到处找转换工具但前提是你要真能看懂每种格式里存的是什么。2.1 1000张图片对金具检测意味着什么1000张图在目标检测里属于“中小规模数据集”。拿它训练YOLO如果类别控制在五类以内配合预训练权重和合理的数据增强完全能训练出可用的检测模型如果类别开到十几类就需要靠划分策略和超参数来补足样本量。电力金具的特点是类别间样本数量天然不平衡绝缘子串在图片里出现频率高均压环、防震锤的出现频率明显低这种分布会直接影响后面的训练效果。所以拿到数据后先统计一下每张图包含的检测框数、每个类别的实例总数这份统计结果比图片总数更能决定你的训练策略。2.2 VOC、COCO、YOLO格式的字段差异与常见混淆三种格式本质上是同一种东西的三种表达方式但关键字段的语义经常被搞混。格式存储方式坐标定义难点VOCXML文件逐张图一个xmlxmin、ymin、xmax、ymax左上角原点像素值需要解析XML标签树多个object节点COCO单个JSON文件bbox为[x, y, width, height]左上角原点像素值categories、annotations、images三段结构ID要对齐YOLO每张图一个txtclass_id x_center y_center width height全部归一化到0~1最容易和COCO的[x,y,w,h]混淆尤其是宽度和高度的含义VOC的xml里往往还带difficult、truncated、occluded这类属性它们不参与训练但在做难例分析时有用。COCO的json里必须维护一个统一的category_id到类别名的映射这个映射错一位整个数据集的标签就全错位了。YOLO的txt最简洁但一旦归一化坐标计算错模型训练时loss会剧烈震荡。2.3 用可视化脚本检查标注质量无论数据集是谁标注的训练前画一遍框是最低成本的质检手段。常见做法是写一个脚本把标签和原图叠加渲染出来逐张翻看。这一步能发现三种典型问题标注框偏移、类别标签贴错、以及图片与XML文件名对不上。操作步骤很简单一张图画上所有真实标注框保存到check_visual目录抽看其中百分之二十的图片就够了。import cv2 import os import xml.etree.ElementTree as ET img_dir JPEGImages xml_dir Annotations save_dir check_visual os.makedirs(save_dir, exist_okTrue) # 只抽查前20张图人工过一遍标注框与目标是否对齐 for xml_name in os.listdir(xml_dir)[:20]: xml_path os.path.join(xml_dir, xml_name) tree ET.parse(xml_path) root tree.getroot() img_name root.find(filename).text img_path os.path.join(img_dir, img_name) img cv2.imread(img_path) if img is None: print(图片读取失败:, img_path) continue for obj in root.iter(object): name obj.find(name).text bndbox obj.find(bndbox) xmin int(float(bndbox.find(xmin).text)) ymin int(float(bndbox.find(ymin).text)) xmax int(float(bndbox.find(xmax).text)) ymax int(float(bndbox.find(ymax).text)) # 画框和类别名颜色固定为绿色便于统一检查 cv2.rectangle(img, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2) cv2.putText(img, name, (xmin, max(ymin - 5, 0)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) save_path os.path.join(save_dir, img_name) cv2.imwrite(save_path, img) print(已保存:, save_path)这段脚本的思路很简单把VOC xml里的标注框渲染到原图上人工快速浏览。我用的是绿色框和纯英文类别名位置信息就是原始像素坐标没有做任何缩放这样只要图和xml是同名同一来源画出来的框理论上就是准的。运行后重点看两类情况一是框边缘离目标边缘是否留了太多空白或切掉了目标主体二是类别名是否明显与目标实物不符。如果发现有几十张图的问题都和某个类别有关那多半是标注规范本身的问题比偶发错误更值得处理。3. 做好标签转换与数据集划分脚本怎么写才不留坑虽然这个数据集三种格式都给你了但实际做项目时你经常会拿到只有一种格式的标注转换脚本绕不开。更重要的是即使三种格式齐备训练前也得按自己的逻辑重新划分训练集、验证集和测试集因为默认划分未必符合你的验证需求。这一章给出我常用的VOC转YOLO脚本和划分脚本两个都是可以直接改路径就能跑的版本。3.1 VOC转YOLO的核心公式与边界判断VOC坐标是绝对值像素YOLO需要的是归一化到0~1的中心点坐标和宽高。转换公式不复杂设图片宽度为img_w、高度为img_h标注框为xmin、ymin、xmax、ymax那么归一化后的中心点x坐标为x_center ((xmin xmax) / 2) / img_w宽高则是box_w (xmax - xmin) / img_w这个公式看起来简单但有一个常见的反面写法是直接拿xmax除以img_w当作中心点x那相当于把框的右边缘当成中心整个标注集体右移半个框的宽度训练出来的模型预测框会整体偏移。还有一个边界问题标注框偶尔会越出图片边界比如xmax为负或超过图片宽度。YOLO训练时遇到这种越界框某些框架会自动裁剪有些则直接报错或产生NaN loss最稳妥的做法是在转换时做越界处理。3.2 一个可直接复用的VOC转YOLO脚本下面的脚本处理VOC格式的xml输出YOLO格式的txt同时处理越界和类别映射两个问题。import os import xml.etree.ElementTree as ET from PIL import Image # 类别映射顺序必须和训练时的data.yaml一致 class_names [insulator, damper, spacer, weight, grading_ring] class_to_id {name: idx for idx, name in enumerate(class_names)} xml_dir Annotations img_dir JPEGImages out_dir labels_yolo os.makedirs(out_dir, exist_okTrue) def clamp(value, min_val, max_val): # 越界坐标做截断防止训练时产生nan loss return max(min_val, min(max_val, value)) for xml_name in os.listdir(xml_dir): if not xml_name.endswith(.xml): continue xml_path os.path.join(xml_dir, xml_name) tree ET.parse(xml_path) root tree.getroot() # 读取图片真实尺寸 img_name root.find(filename).text img_path os.path.join(img_dir, img_name) with Image.open(img_path) as img: img_w, img_h img.size txt_lines [] for obj in root.iter(object): name obj.find(name).text if name not in class_to_id: print(未知类别跳过:, name) continue class_id class_to_id[name] bndbox obj.find(bndbox) xmin float(bndbox.find(xmin).text) ymin float(bndbox.find(ymin).text) xmax float(bndbox.find(xmax).text) ymax float(bndbox.find(ymax).text) # 跳过无效框比如宽高为负 if xmax - xmin 0 or ymax - ymin 0: continue # 中心点坐标和宽高全部归一化 x_center ((xmin xmax) / 2) / img_w y_center ((ymin ymax) / 2) / img_h box_w (xmax - xmin) / img_w box_h (ymax - ymin) / img_h # 关键越界截断但截断后重新计算中心点 x_center clamp(x_center, 0.0, 1.0) y_center clamp(y_center, 0.0, 1.0) box_w clamp(box_w, 0.0, 1.0) box_h clamp(box_h, 0.0, 1.0) txt_lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}) out_name os.path.splitext(xml_name)[0] .txt out_path os.path.join(out_dir, out_name) with open(out_path, w) as f: f.write(\n.join(txt_lines)) print(已转换:, out_name)这段代码有几个关键点要说明。第一类别映射用的是字典而不是直接在xml里取类名当id这样当类别名不统一时能提前暴露问题而不是把错误的id写进标签。第二越界框做了clamp截断而不是跳过因为有些框只是轻微超出边界直接跳过会丢失一部分正样本。但这里有个隐含要求截断之后中心点坐标会改变不能只截断宽高而不重新计算中心点否则框位置和大小会不匹配。第三我默认图片和xml同目录前缀实际项目中如果文件名前缀不一致需要在循环里做一次字符串匹配否则转换出来的txt和图片对不上。3.3 数据集划分脚本避免随机划分带来的类别塌缩得到YOLO格式的标签后下一步是把图片分成训练、验证和测试三份。很多人直接random.shuffle后按比例切这种做法在类别不平衡的数据集上会出问题如果某个类别只出现在少数图片里随机划分很可能把这个类别的样本全部切到训练集里验证集一条都没有导致验证指标虚高。import os import random import shutil from collections import defaultdict random.seed(42) img_dir JPEGImages label_dir labels_yolo train_dir images/train val_dir images/val test_dir images/test train_label_dir labels/train val_label_dir labels/val test_label_dir labels/test for d in [train_dir, val_dir, test_dir, train_label_dir, val_label_dir, test_label_dir]: os.makedirs(d, exist_okTrue) # 统计每个类别出现在哪些图片里 class_to_imgs defaultdict(set) all_imgs set() for label_name in os.listdir(label_dir): if not label_name.endswith(.txt): continue img_name label_name.replace(.txt, .jpg) img_path os.path.join(img_dir, img_name) if not os.path.exists(img_path): print(标签对应的图片不存在:, img_path) continue all_imgs.add(img_name) label_path os.path.join(label_dir, label_name) with open(label_path, r) as f: for line in f: class_id line.strip().split()[0] class_to_imgs[class_id].add(img_name) # 按类别出现次数排序最稀有的类别优先分配 val_ratio, test_ratio 0.15, 0.15 val_imgs, test_imgs set(), set() def assign_images(candidates, target_set, ratio, already_assigned): available candidates - already_assigned count max(1, int(len(available) * ratio)) # 每次取同样本时打乱一次避免固定顺序 chosen set(random.sample(list(available), min(count, len(available)))) target_set.update(chosen) return chosen for class_id in sorted(class_to_imgs.keys(), keylambda c: len(class_to_imgs[c])): imgs class_to_imgs[class_id] assign_images(imgs, val_imgs, val_ratio, val_imgs | test_imgs) assign_images(imgs, test_imgs, test_ratio, val_imgs | test_imgs) train_imgs all_imgs - val_imgs - test_imgs # 复制图片和标签到对应目录 for img_name in train_imgs: shutil.copy(os.path.join(img_dir, img_name), train_dir) shutil.copy(os.path.join(label_dir, img_name.replace(.jpg, .txt)), train_label_dir) for img_name in val_imgs: shutil.copy(os.path.join(img_dir, img_name), val_dir) shutil.copy(os.path.join(label_dir, img_name.replace(.jpg, .txt)), val_label_dir) for img_name in test_imgs: shutil.copy(os.path.join(img_dir, img_name), test_dir) shutil.copy(os.path.join(label_dir, img_name.replace(.jpg, .txt)), test_label_dir) print(f训练集: {len(train_imgs)} 张, 验证集: {len(val_imgs)} 张, 测试集: {len(test_imgs)} 张)这个脚本的思路是稀有类别优先分配先把出现次数最少的类别图片按比例切到验证集和测试集再去分配常见类别。这样能保证每个类别在三个集合里都有一定比例的样本。随机种子固定为42保证每次运行结果一致。需要注意两点一是验证集和测试集的分配对象是类别对应的图片集合一张图可能包含多个类别所以用了already_assigned参数避免重复分配二是最终训练集是全集减去验证集和测试集不会出现漏图。跑完脚本后建议打印每个类别的训练/验证/测试分布人工确认没有出现某个类别在验证集里为零的情况。4. 用这套数据跑通YOLO训练从配置到命令一次说清标签转换和划分都做完后才到了真正训练这一步。标题里带了训练教程但实际的训练流程会因YOLO版本不同而有差异。针对1000张图的中小规模数据集我的建议是优先选YOLOv5s或YOLOv8s这样的轻量模型而不是一上来就上YOLOv8x因为数据量撑不起大模型的参数量强行训练只会得到过拟合的权重。预训练权重去YOLO官方仓库下载即可用COCO预训练权重做初始化比从零训练收敛快得多。4.1 数据配置文件data.yaml的写法与注意事项YOLO训练需要一份数据配置文件里面写清楚类别数量、类别名称、以及训练和验证集的图片路径。这个文件写错是新手最常踩的坑尤其是path那一段的路径层级。train: images/train val: images/val test: images/test nc: 5 names: [insulator, damper, spacer, weight, grading_ring]这里的路径是相对data.yaml所在的目录来解析的。假设你的数据集根目录是/dataset/gold_fittingdata.yaml放在这个根目录下那么train字段就写images/train而不是写完整的绝对路径。如果data.yaml放在别的地方train字段就要相应改成从当前目录到images/train的相对路径。nc必须和names列表的长度一致names的顺序必须和转换脚本里class_to_id的赋值顺序一致顺序错了模型就白训了。我一般还会在验证集路径上多写一个test字段方便训练结束后单独评估测试集。4.2 YOLOv5和YOLOv8的训练命令下面给出YOLOv5和YOLOv8两个版本的训练命令。先看YOLOv5的命令cd yolov5 python train.py \ --data /dataset/gold_fitting/data.yaml \ --weights yolov5s.pt \ --img 640 \ --batch 16 \ --epochs 200 \ --workers 8 \ --project runs/gold_fitting \ --name exp1 \ --patience 30命令参数依次说明--weights指定预训练权重路径如果本地没有yolov5s.pt训练脚本会自动从官方仓库下载--img是输入图片尺寸金具在输电线路巡检图里往往是小目标640是YOLOv5的默认值如果显存允许可以试768甚至896能提升小目标召回率--batch是批大小16在单卡16G显存下比较安全--epochs设200配上patience30后连续30轮验证集指标不提升就提前停。workers设8是数据加载线程数注意不要在Windows上设太大主进程会崩。再看YOLOv8的版本命令结构略有不同cd ultralytics yolo train \ data/dataset/gold_fitting/data.yaml \ modelyolov8s.yaml \ pretrainedyolov8s.pt \ imgsz640 \ batch16 \ epochs200 \ patience30 \ projectruns/gold_fitting \ nameexp1 \ device0YOLOv8用的是keyvalue的参数风格--data这种写法它不认。modelyolov8s.yaml是模型结构定义文件pretrained指定预训练权重。其他参数含义和YOLOv5一致。device0指定用第一块GPU没有GPU的话改成cpu但训练速度会慢十几倍。我这边实际对比过YOLOv5和YOLOv8在同样数据上的验证精度差距不大YOLOv8的部署接口更直观YOLOv5的社区资料更全选哪个取决于你后面要用什么框架做推理服务。4.3 训练时的关键参数怎么调有两个参数对金具检测效果影响最大值得单独拿出来说。第一个是输入尺寸img输电线路巡检图的分辨率通常很高金具在整张图里可能只有几十乘几十像素如果直接缩小到640小目标几乎不可见。我一般的做法是先看标注框在原始图片中的像素尺寸分布如果大量框的宽度在20像素以下训练时把输入尺寸提升到896同时配合多尺度训练。代价是显存占用和训练时间都会翻倍但对于小目标场景值得。第二个是mosaic数据增强。YOLOv5和YOLOv8都默认开启mosaic它把四张图拼在一起训练对小目标检测有提升但在电力金具场景里有个副作用拼接时随机裁剪可能把金具切成半截模型学到的是残缺特征。常见做法是训练到后半段关闭mosaicYOLOv5里在train.py的hyp参数中调整YOLOv8可以用命令行参数直接关yolo train ... \ mosaic0.0 \ close_mosaic10mosaic0.0把增强概率设为0close_mosaic是最后多少轮关闭mosaic。上面这串命令表示第10轮开始彻底关闭mosaic。我个人的经验是数据集本身只有1000张mosaic带来的样本多样性收益大于它造成的特征截断损失前150轮保持默认mosaic最后50轮关闭效果最稳定。4.4 训练日志里要盯的关键指标训练启动以后不是放着不管。loss曲线和验证指标至少要每20轮看一次。重点关注训练损失和验证损失的差距如果训练损失持续下降但验证损失在某个点开始反弹模型已经过拟合了这时应该停止训练而不是继续跑完200轮。金具检测的验证指标里mAP50会比mAP50:95好看很多这是正常的前者对框的位置精度不敏感后者严格要求框的定位和大小都接近真实值。如果mAP50在0.8以上但mAP50:95不到0.3说明模型能检测到目标但定位不准需要检查标注框本身是否够紧凑。5. 训练避坑最容易翻车的5个地方与排查思路训练这一路会遇到多种状况下面5条是我的经验中高频出现的问题按“现象→原因→解决”的方式整理出来。5.1 训练loss不降反升验证集指标一直为零现象训练到第20轮时loss还在0.1徘徊验证集mAP始终是0。 原因标签和图片没对上。最常见的情况是转换脚本和划分脚本用了两套文件名规则导致验证集里的图片和标签前缀不一致模型在验证集上根本找不到对应的标注。具体表现是训练集有框可学验证集全是空标签模型预测出来的框无法匹配任何真实框mAP0也就顺理成章了。 解决训练前先人工抽查验证集的一对同名图片和txt确认图片里确实有目标且txt内容不为空。再检查data.yaml的路径和实际目录结构是否一致比如目录多了一层或少了一层。用下面对比文件名列表的代码打一次集合差就一目了然。ls images/val | sort val_imgs.txt ls labels/val | sed s/.txt/.jpg/ | sort val_labels.txt diff val_imgs.txt val_labels.txtdiff命令没有任何输出就说明图片和标签文件名完全对齐。如果有输出把不匹配的名字打印出来先去处理文件命名。5.2 训练正常但推理时检测不到小目标现象loss从2.0降到0.3验证集mAP50也到0.7了但把模型放到640x640的原图上推理绝缘子一个都框不出来。 原因训练时的输入尺寸和推理时的输入尺寸不一致。训练用768或896推理默认用640相当于模型在一个分辨率上学到的特征尺度在另一个分辨率上做预测小目标的特征尺度错位了。另一个原因是没有开启推理端的TTA或多尺度预测YOLO默认只按单尺度跑。 解决推理时显式指定和训练相同的imgsz参数同时把推理的置信度阈值降低。比如训练用了896推理就写imgsz896。这问题不是模型没学好而是参数没对齐。另外可以做一个简单的验证把原图按比例缩小到训练尺寸后推理如果此时能检出基本可以确认是尺度问题。5.3 形状不规则的类别总是“露出半个框”现象检出的结果里绝缘子这种长条形的目标框通常偏宽均压环这种圆形目标框偏大几乎每个预测框都比真实目标的大一圈。 原因标注框本身太大。很多标注员在框长条形目标喜欢留白导致标注框面积远大于实际目标面积。这会让模型学到“框可以松一点”的惰性边界预测框自然就松散。另一个可能是不属于金具的目标被标进去了比如绝缘子旁边一串引线也被画进去。 解决把标注框和实际目标的占比做一个统计筛选出宽高比异常或面积占比过大的标注框重新修正。没有更好办法只能人工复查。如果原始数据来自别人的标注这个问题尤其严重因为标注规范和你自己的标准不同。5.4 BN层崩溃train loss突然变成NaN现象训练进行到第60轮左右loss在某一步突然变成nan然后一直无法恢复。 原因最常见的是批次大小过小且开启了BN每个batch里的样本数太少BN的均值和方差估算不稳定数值计算溢出。batch size为2甚至为1时特别容易触发。另外如果标签里出现了0宽度或0高度的框某些版本的YOLO在计算损失时会除零直接产生nan。 解决把batch size提到8以上同时检查标签txt里是否有宽度或高度为0的行。第三章节的转换脚本已经过滤了这类框但如果用别人转好的标签要再跑一遍检查脚本。批量检测可以写一段小代码读取所有txt文件并过滤掉坐标异常的行确保每个框的宽高数值都在(0,1]区间内。如果显存不够撑大batch就用梯度累积YOLOv8里batch可以用batch4加上accumulate4达到等效16的效果。5.5 混淆矩阵里某个类别的检出率很低但总体mAP不低现象mAP50整体0.75看起来很体面但拆开看混淆矩阵发现防震锤这个类别的召回率只有0.3大部分被漏检了。 原因样本数量太少。防震锤在1000张图片里可能只出现几十次模型见过太少特征没学出来。整体mAP被绝缘子这种高频类别拉高了掩盖了个别类别的短板。 解决先加数据集中的类别权重YOLO支持class_weights参数给稀有类别分配更高的损失权重其次是对稀有类别的样本做复制粘贴的数据增强在图片的不同位置重复粘贴防震锤的裁剪图相当于扩充样本量。还有一种思路是单独用稀有类别的图片做二次微调不过这种做法容易破坏已学好的特征权重设置要保守一些。先看数据和分布再定方案如果加了权重、做了扩充稀有类别的召回率还是拉不起来就得考虑是不是标注类别本身就有问题比如和另一个类别在视觉上高度相似。6. 训练完别急着部署用验证结果反推下一轮调优模型训练结束后第一个动作不是导出权重去部署而是先看验证集的详细结果用错误分析指导下一轮调优。常见做法是跑一遍验证集并保存每个类别的精确率、召回率和置信度曲线。查看测试集效果的命令YOLOv8可以这样yolo val \ data/dataset/gold_fitting/data.yaml \ modelruns/gold_fitting/exp1/weights/best.pt \ imgsz896运行结束后results目录下会生成混淆矩阵和一张PR曲线图。PR曲线里每个类别有一条线曲线越靠近右上角说明该类别的检测效果越好。如果某个类别的曲线明显下凹说明该类别的置信度和召回率之间的权衡存在问题可以试着调低该类别的置信度阈值。另外一个有参考价值的文件是标注框宽高分布图图上能清楚看到哪些尺寸的金具框占大多数如果训练用的anchor和这个分布相差过大就需要用auto_anchor重新计算anchor尺寸。置信度阈值的调整也有讲究。YOLO默认的置信度阈值是0.25但对于小目标金具0.25常常会漏掉大量低置信度的真目标。合理的做法是把阈值下调到0.1先看漏检多还是误检多再决定最终部署阈值。误检偏多就把阈值调回0.3漏检偏多就维持在0.1到0.15之间。我自己的习惯是每一轮训练后都花半小时做错误分析从验证集结果里挑出二十张检测失败的图片分三类记录错过的目标、误检的背景和定位不准确的框。二十张看完基本能判断下一次优化的方向。如果错过的目标集中在少数类别就去扩该类的训练样本如果误检集中在线路背景就考虑给训练集补充一些没有金具的负样本。这套流程走过两三轮模型的精度往往还能再拉上几个点。作为收尾再把权重导出和推理验证串起来。测试通过后YOLOv8导出为onnx格式用onnxruntime在CPU上跑一两张真实图片看推理速度和检测效果是否符合预期。这个环节建议在白天光线正常的场景下做和训练集里的图片场景接近结果更有参考价值。希望这套从数据检查到训练调优的流程对你有所帮助。我第一次拿到类似数据集时省略了可视化检查直接开训结果浪费了整整一天在排查验证集指标为零的问题后来才学会了先把数据文件对齐再动手训练的顺序。这个习惯值得保留。本文还有配套的精品资源点击获取
返回列表