yolov8中的parse_model函数用法

目前很多博主讲parse_model函数的工作原理,却不讲它的用法,导致我对模型的搭建仍旧一知半解,经过分析代码,parse_model只是提供了一个搭建的模板,并不是真的搭建了模型,下面讲解parse_model之后的模型搭建步骤。

yolov8中的parse_model在ultralytics/nn/tasks.py中,关于parse_model函数的原理可观看视频:【yolov5 网络搭建 代码精讲-哔哩哔哩】 https://b23.tv/4s13Atd 

yolov5和yolov8的parse_model几乎没有区别

关于parse_model之后的用法,同样在tasks.py中找到DetectionModel类,在该类中有一行代码:

self.model, self.save = parse_model(deepcopy(self.yaml), ch=ch, verbose=verbose)  # model, savelist

记住这条代码赋予了DetectionModel类两个属性:self.model与self.save

按ctrl点击self.save,跳转到如图所示581行,进入真正的用法

68db8a3b7cdd403f802449663472b5ac.png

跳转到的代码如下所示:

    def predict(self, x, profile=False, visualize=False, batch=None, augment=False, embed=None):
        """
        Perform a forward pass through the model.

        Args:
            x (torch.Tensor): The input tensor.
            profile (bool, optional): If True, profile the computation time for each layer. Defaults to False.
            visualize (bool, optional): If True, save feature maps for visualization. Defaults to False.
            batch (dict, optional): Ground truth data for evaluation. Defaults to None.
            augment (bool, optional): If True, perform data augmentation during inference. Defaults to False.
            embed (list, optional): A list of feature vectors/embeddings to return.

        Returns:
            (torch.Tensor): Model's output tensor.
        """
        y, dt, embeddings = [], [], []  # outputs
        for m in self.model[:-1]:  # except the head part即检测头,nn.Sequential对象中的最后一个模块
            if m.f != -1:  # if not from previous layer
                x = y[m.f] if isinstance(m.f, int) else [x if j == -1 else y[j] for j in m.f]  # from earlier layers
            if profile:
                self._profile_one_layer(m, x, dt)
            x = m(x)  # run
            y.append(x if m.i in self.save else None)  # save output
            if visualize:
                feature_visualization(x, m.type, m.i, save_dir=visualize)
            if embed and m.i in embed:
                embeddings.append(nn.functional.adaptive_avg_pool2d(x, (1, 1)).squeeze(-1).squeeze(-1))  # flatten
                if m.i == max(embed):
                    return torch.unbind(torch.cat(embeddings, 1), dim=0)
        head = self.model[-1]
        x = head([y[j] for j in head.f], batch)  # head inference
        return x

predict是类RTDETRDetectionModel中的一个方法,而类RTDETRDetectionModel继承了DetectionModel类,因此拥有属性self.model和self.save,已知parse_model的返回值如下:

return nn.Sequential(*layers), sorted(save)

 因此predict方法中的self.model就是parse_model的返回值中的nn.Sequential(*layers),这是一个按顺序排列的模板,并不是模型主体,predict详细讲解了模型的搭建过程,下面详细讲解该代码中重要的部分:

for m in self.model[:-1]:

遍历模型的所有层,除了最后一层,即检测头部分

if m.f != -1:  # if not from previous layer
    x = y[m.f] if isinstance(m.f, int) else [x if j == -1 else y[j] for j in m.f]  # from earlier layers

(这段代码中的m.f需要注意,其来自于parse_model中的语句:m_.i, m_.f, m_.type = i, f, t)

此处的x表示当前层的输入,如果当前层不是从上一层直接传过来的(m.f!=-1),则从y列表中获取对应输入:如果m.f是整数,则表示单一层的索引,如果m.f是一个列表,则表示当前层的输入来自多个层的输出。

举个例子:如果m.f=[-1,2,3],可知其是一个列表,因此当前层的输入来自上一层、第2层和第3层的输出,因此x=[x,y[2],y[3]],注意列表中的x是上一层的输出。

x=m(x)

此时等号左边的x表示当前层的输出,也是下一层的输入。

y.append(x if m.i in self.save else None)  # save output

将当前层的输出结果保存以便下一次循环使用,注意m.i属性来自于parse_model函数,self.save是parse_model的返回值。

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值