直接上结论:

当c3k=True时,C3k2为 C2f(C3),外层为C2f,内层将Bottleneck换成可控制卷积核的C3

当c3k=False时,C3k2为 C2f

解释如下:

通过yolov11的Yaml文件可以看出来,yolov8中的C2f模块均被换成了C3k2模块,而且C3k2模块在backbone和neck中有True有False,这到底有什么区别呢?

看源码!!!!!!!!!!!

从源码中可以看出,C3k2模块只做了两件事:

1. 继承C2f
2. 重新初始化self.m

继承C2f模块也就是说继承了他的一切(包括初始化参数与前向传播),对C2f中的self.m进行了改变

self.m = nn.ModuleList(
            C3k(self.c, self.c, 2, shortcut, g) if c3k else Bottleneck(self.c, self.c, shortcut, g) for _ in range(n)
        )

从上述代码就可以看出yaml文件中的True与False代表了什么了,就是这里的c3k

c3k = True时,self.m就是C3k这个模块

而C3k又继承了C3模块,那么区别在哪里呢?区别就在self.m


# C3
self.m = nn.Sequential(*(Bottleneck(c_, c_, shortcut, g, k=((1, 1), (3, 3)), e=1.0) for _ in range(n)))

# C3k
self.m = nn.Sequential(*(Bottleneck(c_, c_, shortcut, g, k=(k, k), e=1.0) for _ in range(n)))

通过源码可以看到,可以说基本没任何区别,区别就在添加了一个可控制参数k,可以控制C3中self.m的卷积核大小

c3k = False时,self.m就是Bottleneck这个模块

如C2f中的self.m,与C3k2中的保持一致

# C3k2
        self.m = nn.ModuleList(
            C3k(self.c, self.c, 2, shortcut, g) if c3k else Bottleneck(self.c, self.c, shortcut, g) for _ in range(n)
        )

# C2f
self.m = nn.ModuleList(Bottleneck(self.c, self.c, shortcut, g, k=((3, 3), (3, 3)), e=1.0) for _ in range(n))

YOLOv11 Bottleneck与YOLOv8没有改变,上图为v8

因此可以说当c3k = False时,C3k2就是C2f,一模一样

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐