在进行一篇文章的网络结构复现时,其网络结构有一部分是vgg结构。在使用tensorboard对整体网络结构进行可视化的时候发现vgg结构的FC层疯狂报错。先贴出源码:
'''
这是网络设置部份
'''
self.maxpool = nn.MaxPool2d(2, 2)
# conv1
self.conv1_1 = nn.Conv2d(2, 64, 3, padding=1)
# conv2
self.conv2_1 = nn.Conv2d(64, 128, 3, padding=1)
# conv3
self.conv3_1 = nn.Conv2d(128, 256, 3, padding=1)
self.conv3_2 = nn.Conv2d(256, 256, 3, padding=1)
# conv4
self.conv4_1 = nn.Conv2d(256, 512, 3, padding=1)
self.conv4_2 = nn.Conv2d(512, 512, 3, padding=1)
# conv5
self.conv5_1 = nn.Conv2d(512, 512, 3, padding=1)
self.conv5_2 = nn.Conv2d(512, 512, 3, padding=1)
self.dropout = nn.Dropout2d(p=0.5,inplace=True)
# fc
self.fc1 = nn.Linear(512 * 4 * 4, 1024)
self.fc2 = nn.Linear(1024, 1024)
'''
这是网络的forward部份
'''
x = self.maxpool(F.leaky_relu(self.conv1_1(x)))
x = self.maxpool(F.leaky_relu(self.conv2_1(x)))
x = self.maxpool(F.leaky_relu(self.conv3_2(F.leaky_relu(self.conv3_1(x)))))
x = self.maxpool(F.leaky_relu(self.conv4_2(F.leaky_relu(self.conv4_1(x)))))
x = self.maxpool(F.leaky_relu(self.conv5_2(F.leaky_relu(self.conv5_1(x)))))
x = self.dropout(x)
x = F.leaky_relu(self.fc1(x))
x = F.leaky_relu(self.fc2(x))
tensorboard可视化结构部份为:
if __name__ == '__main__':
output = t.rand(1,2,128,128)
model = RDANet()
with SummaryWriter(comment='RDANet') as w:
w.add_graph(model, output)
从这可以看出我的网络结构input为128 * 128 * 2的矩阵。在此处另有的一坑就是需要对conv2d层设置padding=1(因为kernel_size=3所以填1),不然的话每一个conv后原矩阵的W和H均会变小。具体计算见pytorch官网。而带来的影响就是你在计算池化后的W和H时会惊讶的发现和你所设想的不太一样。也因此会带来一系列的报错。
接下来就进入了全连接层的大坑了。在我的想法中在进入第一个FC层时输出应该是 [1,2014] ,因为在dropout层之后x.size 为 [1,512,4,4] ,因此若想FC层输出为 [1,2014] 的话FC层应该为 (512 * 512 * 4,2014) ,然而你会发现报错为m1=[2014 * 4], m2=[8196 * 2014]。从这个报错能看出来,pytorch将输入的前三参数合并,因此导致了两者维度不一致。所以解决方案很简单
x = self.maxpool(F.leaky_relu(self.conv1_1(x)))
x = self.maxpool(F.leaky_relu(self.conv2_1(x)))
x = self.maxpool(F.leaky_relu(self.conv3_2(F.leaky_relu(self.conv3_1(x)))))
x = self.maxpool(F.leaky_relu(self.conv4_2(F.leaky_relu(self.conv4_1(x)))))
x = self.maxpool(F.leaky_relu(self.conv5_2(F.leaky_relu(self.conv5_1(x)))))
x = self.dropout(x)
#加入这一段
x = x.view(x.size(0), 512 * 4 * 4)
x = F.leaky_relu(self.fc1(x))
x = F.leaky_relu(self.fc2(x))
x = np.array(x).reshape(self.image_size[0]/2,self.image_size[1]/2)
在此处我也曾加过x = x.view(-1, 512 * 4 * 4),然而输出还是为x.size()还是为[1,512,4,4]这就使我非常困扰。因此最终解决方案还是为x = x.view(x.size(0), 512 * 4 * 4) 这样x.size()就为 [1,8196],这样经过FC层之后输出就为 [1,2014] 这样输出就正确了。