YOLOv7训练时4个类别只出2个类别

正常是4个类别:

但是YOLOv7训练完后预测总是只有两个类别:

而且都是LFM和SFM

我一开始检查了下特征图大小,如果输入是640*640的话,三个尺度特征图是80*80,40*40,20*20;如果输入是416*416的话,三个尺度特征图是52*52,26*26,13*13。我一开始以为是信号太窄了,特征图大小设置有问题,但实际上在YOLOv3,YOLOv10下用的同样大小的特征图,YOLOv3,YOLOv10挺好使的。

后来检查了下anchors,用的是YOLO默认的anchors大小,和YOLOv3下用的一样(YOLOv3好使,别问YOLOv10下多少,YOLOv10是anchor-free的)

anchors =
array([
[ 10., 13.],[ 16., 30.],[ 33., 23.],
[ 30., 61.],[ 62., 45.],[ 59., 119.],
[116., 90.],[156., 198.],[373., 326.]
])

最后发现可能是detect.py下conf-thres参数的问题,这个参数不能太高,一开始我设的0.5,后来调到0.1就好了,设0.5的时候其实还是有极少的BPSK,Frank的类别是预测出来了的

if __name__ == '__main__':
    parser.add_argument('--conf-thres', type=float, default=0.1, help='object confidence threshold')
    parser.add_argument('--iou-thres', type=float, default=0.3, help='IOU threshold for NMS')

除了conf-thres,以下内容也是我检查过程中总结出来需要注意的

首先注意类别预测滤波器不要开

if __name__ == '__main__':
    parser.add_argument('--classes', nargs='+', type=int, help='filter by class: --class 0, or --class 0 2 3')

NMS操作时可以不使用classes参数 

# Apply NMS
# pred = non_max_suppression(pred, opt.conf_thres, opt.iou_thres, classes=opt.classes, agnostic=opt.agnostic_nms)
pred = non_max_suppression(pred, opt.conf_thres, opt.iou_thres,  agnostic=opt.agnostic_nms)

另外一个就是YOLOv7的train.py下有这么两句话

# hyp['cls'] *= nc / 80. * 3. / nl  # scale to classes and layers
# hyp['obj'] *= (imgsz / 640) ** 2 * 3. / nl  # scale to image size and layers
hyp['cls'] *= nc / 4. * 3. / nl  # scale to classes and layers
hyp['obj'] *= (imgsz / 416) ** 2 * 3. / nl  # scale to image size and layers

类别数和图片大小记得改成自己的


某段时间我以为是那两个预测出来的类训练的不好,于是我记录了训练过程的各个类的loss值

具体方法是在:yolov7主路径/utils/loss.py下面写了一个函数

    def save_every_class_loss_txt(self,pred_class, t):
        # zhouzhichao
        # 计算每个类别的损失
        self.class_loss_save_times = self.class_loss_save_times + 1
        # print("self.class_loss_save_times:",self.class_loss_save_times)
        if self.class_loss_save_times%50!=0:
            return
        TXT_PATH = "D:\实验室\论文\论文-多信号参数估计\实验\YOLOv7\yolov7-main\\runs\class_loss.txt"
        class_losses = []
        for c in range(4):
            ps_c = pred_class[:, c]  # 提取第c个类别的预测
            t_c = t[:, c]  # 提取第c个类别的真值
            loss_c = self.BCEcls(ps_c, t_c)  # 计算单类别损失
            # class_losses.append(round(loss_c.item(), 3))  # 保留4位小数
            class_losses.append(f"{loss_c.item():.3f}")  # 使用 f-string 格式化

        # 转换为制表符分隔的字符串
        line = "\t".join(class_losses) + "\n"

        # 追加写入文件
        with open(TXT_PATH, "a", encoding="utf-8") as f:
            f.write(line)
class ComputeLossOTA:
    # Compute losses
    def __init__(self, model, autobalance=False):
        super(ComputeLossOTA, self).__init__()
        device = next(model.parameters()).device  # get model device
        h = model.hyp  # hyperparameters
        self.class_loss_save_times = 0

函数在ComputeLossOTA的__call__下调用:

# Classification
selected_tcls = targets[i][:, 1].long()
if self.nc > 1:  # cls loss (only if multiple classes)
   t = torch.full_like(ps[:, 5:], self.cn, device=device)  # targets
   t[range(n), selected_tcls] = self.cp
   lcls += self.BCEcls(ps[:, 5:], t)  # BCE
   self.save_every_class_loss_txt(ps[:, 5:], t)

原本计算的是全部类别的损失值: 

lcls += self.BCEcls(ps[:, 5:], t)  # BCE

我就拓展了下写出了save_every_class_loss_txt函数用于记录训练过程每个类别的损失值

画图的话就从txt里复制,粘贴到excel或origin都行,如下图

发现所有类别的损失值下降趋势看起来并没什么问题

这也使得我将预测类别缺失的问题限制在预测的阈值和Iou值设置上面了,最终调整阈值解决了问题

<think>嗯,用户想知道如何在YOLOv5中仅训练三个类别的模型。首先,我需要回忆YOLOv5的配置步骤。YOLOv5通常需要数据集和配置文件,比如dataset.yaml和模型结构文件。 根据引用[1],用户需要设置dataset.yaml文件,里面包含类名和路径。所以,用户应该修改这个文件中的类别数,把原来的类别换成自己的三个类别。比如,把names下的类别改为三个。同,确保训练、验证和测试的图片路径正确。 然后,模型结构配置,比如yolov5s.yaml,里面的nc参数代表类别数,需要从原来的80改为3。这样模型输层才能对应三个类别。引用[1]提到了使用--cfg指定模型配置,所以用户应该在训练命令里指定修改后的yolov5l.yaml或者其他版本,同nc设为3。 接下来,检查数据集是否正确标注。YOLOv5使用txt格式的标注,每行是class_id和归一化后的坐标。用户需要确认所有标注文件中的class_id都是0到2,对应三个类别。如果有其他class_id,训练错。 训练命令方面,引用[1]中的例子用了--img 640,--batch 16,--epochs 300等参数。用户需要调整这些参数,特别是--data指向新的dataset.yaml,--cfg指向修改后的模型配置。如果预训练权重不适用,可能需要用--weights ''从头开始训练,或者用预训练的但修改输层。 可能遇到的问题包括类别数不匹配导致加载权重失败,这候可能需要调整权重文件的输层。或者数据集路径错误,需要检查路径是否正确。 用户可能还想知道如何验证是否只训练了三个类别,可以查看训练日志中的类别名称,或者在验证检查输是否正确。另外,训练后的模型在推理应该只识别这三个类别。 总结步骤:修改dataset.yaml的类别,调整模型的nc参数,检查标注文件,运行训练命令。确保所有配置正确,避免常见错误。</think>在YOLOv5中仅训练三个类别的模型,需按照以下步骤进行配置: ### 一、数据集准备 1. 标注文件格式需符合YOLOv5要求,每个对象标注为`class_id x_center y_center width_height`的归一化坐标 2. 确保数据集中仅包含目标三个类别的标签,class_id必须为0、1、2(对应三个类别) ### 二、配置文件修改 1. **dataset.yaml**配置示例: ```yaml path: ../datasets/custom train: images/train val: images/val test: images/test names: 0: class1 1: class2 2: class3 # 仅保留三个类别名称[^1] ``` 2. **模型配置文件**修改(如yolov5s.yaml): ```yaml # Parameters nc: 3 # 修改为3个类别 depth_multiple: 0.33 width_multiple: 0.50 ``` ### 三、训练命令 ```bash python train.py --img 640 --batch 16 --epochs 100 \ --data ./data/custom_dataset.yaml \ --cfg ./models/yolov5s_custom.yaml \ --weights yolov5s.pt # 建议使用预训练权重 ``` ### 四、验证关键点 1. 检查`names`字段顺序与标注文件class_id对应关系 2. 确认训练中显示的类别数: ``` Class Images Instances: all 3 3 3 ``` ### 五、常见问题处理 1. **类别不匹配错误**:检查模型配置文件`nc`值是否与dataset.yaml的类别数一致 2. **权重加载失败**:当使用预训练权重,若原模型类别数不同,需添加`--pretrained`参数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值