错误如下:
File "D:\project\boxmot-3.0\boxmot-3.0\./yolov5\models\yolo.py", line 340, in fuse
if isinstance(m, (Conv, DWConv)) and hasattr(m, "bn"):
TypeError: isinstance() arg 2 must be a type or tuple of types
错误位置文件对应如下定义:
def fuse(self):
"""Fuses Conv2d() and BatchNorm2d() layers in the model to improve inference speed."""
LOGGER.info("Fusing layers... ")
for m in self.model.modules():
if isinstance(m, (Conv, DWConv)) and hasattr(m, "bn"):
m.conv = fuse_conv_and_bn(m.conv, m.bn) # update conv
delattr(m, "bn") # remove batchnorm
m.forward = m.forward_fuse # update forward
self.info()
return self
common文件中Conv和 DWConv的定义如下:
def DWConv(c1, c2, k=1, s=1, act=True):
# Depthwise convolution
return Conv(c1, c2, k, s, g=math.gcd(c1, c2), act=act)
class Conv(nn.Module):
# Standard convolution
def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True): # ch_in, ch_out, kernel, stride, padding, groups
super(Conv, self).__init__()
self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False)
self.bn = nn.BatchNorm2d(c2)
self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity())
def forward(self, x):
return self.act(self.bn(self.conv(x)))
def fuseforward(self, x):
return self.act(self.conv(x))
DWConv
函数实际上并没有返回一个新的类实例,而是调用了 Conv
类并返回了一个 Conv
实例。这意味着 DWConv
并不是一个类类型,而是一个函数,它返回的是 Conv
类的实例。因此,在 fuse
方法中使用 isinstance(m, (Conv, DWConv))
是不正确的,因为 DWConv
不是一个类型,而是一个函数。
为了解决这个问题,需要在 fuse
方法中检查模块是否是 Conv
类的实例,并且如果它是通过 DWConv
函数创建的(即具有特定的属性或结构),则需要额外处理。但是,由于 DWConv
只是调用了 Conv
并没有引入新的类,因此实际上只需要检查 m
是否是 Conv
的实例。
不过,为了保持代码的清晰和可维护性,可以考虑在 Conv
类中添加一个额外的属性来标记它是否是通过 DWConv
函数创建的。但是,在这个特定的情况下,由于 DWConv
仅仅设置了 groups
参数,并且这个参数在 Conv
类的构造函数中已经处理,其实不需要做这种区分。
因此,可以简单地修改 fuse
方法,只检查 m
是否是 Conv
的实例:
def fuse(self):
"""Fuses Conv2d() and BatchNorm2d() layers in the model to improve inference speed."""
LOGGER.info("Fusing layers... ")
for m in self.model.modules():
if isinstance(m, Conv) and hasattr(m, "bn"):
m.conv = fuse_conv_and_bn(m.conv, m.bn) # update conv
delattr(m, "bn") # remove batchnorm
m.forward = m.forward_fuse # update forward
self.info()
return self
一般情况下将上面代码替换原来的就可以解决错误了。
注意,这里假设 fuse_conv_and_bn
函数已经正确定义,并且 forward_fuse
方法也在 Conv
类中定义好了。
另外,如果 Conv
类中的 forward_fuse
方法还没有定义,你需要添加它,以便在融合卷积层和批归一化层后使用。这个方法应该类似于原始的 forward
方法,但是不需要调用 bn
层。
class Conv(nn.Module):
# ...(其他代码保持不变)
def forward_fuse(self, x):
return self.act(self.conv(x))
最后,请确保 LOGGER
已经被正确定义,否则代码将在尝试记录信息时抛出另一个错误。如果 LOGGER
没有定义,可以使用 Python 的标准日志库来创建一个:
import logging
LOGGER = logging.getLogger(__name__)
LOGGER.setLevel(logging.INFO)
# 如果需要,可以添加日志处理器来将日志输出到控制台或文件