如何更改densenet121
模型中的out_features
?
我使用下面的代码来训练模型:
from torch.nn.modules.dropout import Dropout
class Densnet121(nn.Module):
def __init__(self):
super(Densnet121, self).__init__()
self.cnn1 = nn.Conv2d(in_channels=3 , out_channels=64 , kernel_size=3 , stride=1 )
self.Densenet_121 = models.densenet121(pretrained=True)
self.gap = AvgPool2d(kernel_size=2, stride=1, padding=1)
self.bn1 = nn.BatchNorm2d(1024)
self.do1 = nn.Dropout(0.25)
self.linear = nn.Linear(256,256)
self.bn2 = nn.BatchNorm2d(256)
self.do2 = nn.Dropout(0.25)
self.output = nn.Linear(64 * 64 * 64,2)
self.act = nn.ReLU()
def densenet(self):
for param in self.Densenet_121.parameters():
param.requires_grad = False
self.Densenet_121.classifier = nn.Linear(1024, 1024)
return self.Densenet_121
def forward(self, x):
img = self.act(self.cnn1(x))
img = self.densenet(img)
img = self.gap(img)
img = self.bn1(img)
img = self.do1(img)
img = self.linear(img)
img = self.bn2(img)
img = self.do2(img)
img = torch.flatten(img, 1)
img = self.output(img)
return img
在训练这个模型时,我遇到了以下错误:
RuntimeError: Given groups=1, weight of size [64, 3, 7, 7], expected input[64, 64, 62, 62] to have 3 channels, but got 64 channels instead
您的第一个转换层输出形状为(b, 64, h, w)
的张量,而下一层,密集模型期望3个通道。因此引发了错误:
"预期输入[…]有3个通道,但得到64通道,而不是">
不幸的是,这个值在Densenet类的源代码中是硬编码的,参见参考资料。
然而,一种解决方法是在初始化密集网络后覆盖第一个卷积层。像这样的代码应该可以工作:# First gather the conv layer specs
conv = self.Densenet_121.features.conv0
kwargs = {k: getattr(conv, k) for k in
('out_channels', 'stride', 'kernel_size', 'padding', 'bias')}
# overwrite with identical specs with new in_channels
model.features.conv0 = nn.Conv2d(in_channels=64, **kwargs)
或者你可以这样做:
w = model.features.conv0.weight
w.data = torch.rand(len(w), 64, *w.shape[:2])
替换底层卷积层权重而不影响其元数据(例如:conv.in_channels
仍然等于3
),这可能有副作用。因此,我建议采用第一种方法。