YoloV5模型加入DenseNet时出现的问题

作者您好,我在看您对yolov7模型加入DenseNet模块的文章并且实践,想请问一下我是用YoloV5来做实践的,在这里里面我在parse_model函数当中加入您所说的代码时会出现报错,我应该怎么解决这一问题呢?

img

img

包括您下面所说的网络配置我应该怎么样配置呢?

必须先有if才能有elif,你直接用elif肯定报错

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 这个问题的回答你可以参考下: https://ask.csdn.net/questions/7419203
  • 除此之外, 这篇博客: Yolov5(2):模型解析与构建源码逐行解析中的 二、 parse_model函数解析 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:
    def parse_model(d, ch):  # model_dict, input_channels(3)
        # 打印模型中各层参数--表头
        # LOGGER.info中 '':>3    表示靠右对齐,统一占位大于等于3
        #        'module':<40    表示靠左对齐,统一占位大于等于40
        LOGGER.info(f"\n{'':>3}{'from':>18}{'n':>3}{'params':>10}  {'module':<40}{'arguments':<30}")
        # anchors:预选框
        # nc     :类别数
        # depth_multiple: 网络深度防缩因子
        # width_multiple: 网络通道数防缩因子
        anchors, nc, gd, gw = d['anchors'], d['nc'], d['depth_multiple'], d['width_multiple']
        # 得到一层的预选框的个数
        na = (len(anchors[0]) // 2) if isinstance(anchors, list) else anchors  # number of anchors
        # 每一个预选框包含 nc+5 个预测值,其中nc个值用来预测类别,2个用来预测位置调整,2个用来预测预测框尺寸调整,1个用来判别是否有目标
        no = na * (nc + 5)  # number of outputs = anchors * (classes + 5)
        # layers:保存每一层
        # save  :为残差连接的concat暂存中间调整图
        # c2    :当前模块的input_channel
        layers, save, c2 = [], [], ch[-1]  # layers, savelist, ch out
        # 构建模型
        # from:前一残差模块索引, number:深度, module:模块名, args:参数
        for i, (f, n, m, args) in enumerate(d['backbone'] + d['head']):
            # 实例化模块
            m = eval(m) if isinstance(m, str) else m  # eval strings
            for j, a in enumerate(args):
                try:
                    # 将参数字符串转换为参数数值
                    args[j] = eval(a) if isinstance(a, str) else a  # eval strings
                except NameError:
                    pass
            # round(n * gd): 放缩模块深度,四舍五入
            n = n_ = max(round(n * gd), 1) if n > 1 else n  # depth gain
            # 处理第一类模块,这一类模块的参数类似:
            # 输入、输出通道数、
            if m in [Conv, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, MixConv2d, Focus, CrossConv,
                     BottleneckCSP, C3, C3TR, C3SPP, C3Ghost]:
                # 每处计算c2目的是作为下一层的输入通道数
                c1, c2 = ch[f], args[0]
                # 判断是否为最终输出,否则输出通道数要经过放缩为模型量级
                if c2 != no:
                    # 将c2限定下界为 8 , make_divisible返回的是 max(ceil(c2 * gw / 8) * 8, 8)
                    c2 = make_divisible(c2 * gw, 8)
                # 装入参数列表:输入通道数、输出通道数、其他参数
                args = [c1, c2, *args[1:]]
                # 处理第一类模块中的部分模块,这一类模块的参数:
                # 第三个参数额外多一个深度
                if m in [BottleneckCSP, C3, C3TR, C3Ghost]:
                    args.insert(2, n)  # number of repeats
                    n = 1
            # 处理第二类模块参数,仅仅需要一个通道数作为正则化参数
            elif m is nn.BatchNorm2d:
                args = [ch[f]]
            # 处理第三类模块参数,计算出拼接后的通道数
            elif m is Concat:
                c2 = sum(ch[x] for x in f)
            # 处理第四类模块参数,目标检测模块
            elif m is Detect:
                # 此模块参数为:[nc, anchors, [layer1_ch, layer2_ch, layer3_ch]]
                # 三层特征图的通道数
                args.append([ch[x] for x in f])
                # 如果anchors为整数,表明传入的是预选框个数,则生成anchors数对表示预选框,len(f)表示层数
                if isinstance(args[1], int):  # number of anchors
                    args[1] = [list(range(args[1] * 2))] * len(f)
            # 处理第五类模块参数, 图像切割,例如(1,3,20,20)-->(1,12,10,10),传入参数为切割比例
            # 进而计算出输出的通道数为c2
            elif m is Contract:
                c2 = ch[f] * args[0] ** 2
            # 处理第六类模块参数,是Contract的逆过程
            elif m is Expand:
                c2 = ch[f] // args[0] ** 2
            else:
            # 其他模块
                c2 = ch[f]
            # 逐个构建模块,对于多层的进行展开重构为整体,目的是提高效率,节省空间
            m_ = nn.Sequential(*(m(*args) for _ in range(n))) if n > 1 else m(*args)  # module
            # 例如:"<class 'torch.nn.modules.conv.Conv2d'>",目的为修改类型
            t = str(m)[8:-2].replace('__main__.', '')  # module type
            # numel()获取tensor的元素总个数,np就是总参数量
            np = sum(x.numel() for x in m_.parameters())  # number params
            # 修改模块的信息,便于后续制表格式打印
            m_.i, m_.f, m_.type, m_.np = i, f, t, np  # attach index, 'from' index, type, number params
            LOGGER.info(f'{i:>3}{str(f):>18}{n_:>3}{np:10.0f}  {t:<40}{str(args):<30}')  # print
            # 为残差连接的concat暂存中间调整图,同时也为可视化提供帮助
            save.extend(x % i for x in ([f] if isinstance(f, int) else f) if x != -1)  # append to savelist
            layers.append(m_)
            # 处理边界
            if i == 0:
                ch = []
            ch.append(c2)
        return nn.Sequential(*layers), sorted(save)

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^