backbone的意思就是骨干网络,backbone+head subnet就可以组成一个目标检测网络,为了有一个好的初始值以及加快训练,往往会使用imagenet的预训练模型作为backbone,以vgg16作为backbone为例。
上节说到就是在vgg中间塞一个rpn,也就是在分类的全连接层之前加rpn,那么我们把这两部分分开。用的是torchvision的实现和预训练模型。
def load_backbonevgg16(pretrained=True,**kwargs):
model=vgg16(pretrained=pretrained, progress=True, **kwargs)
features=list(model.features)[:30]# the 30th layer of features is relu of conv5_3
#freeze top4 conv
for layer in features[:10]:
for p in layer.parameters():
p.requires_grad=False
classifier=list(model.classifier)
#del the last layer
del classifier[6]
#del dropout layer
del classifier[5]
del classifier[2]
return nn.Sequential(*features),nn.Sequential(*classifier)
vgg的网络比较简单,就是卷积+maxpooling,每个卷积的通道数如下:
[64, 64, ‘M’, 128, 128, ‘M’, 256, 256, 256, ‘M’, 512, 512, 512, ‘M’, 512, 512, 512, ‘M’],
这么卷积池化后,再加个全局平均池化,再接全连接层就是分类用的vgg。
class VGG(nn.Module):
def __init__(self, features, num_classes=1000, init_weights=True):
super(VGG, self).__init__()
self.features = features
self.avgpool = nn.AdaptiveAvgPool2d((7, 7))
self.classifier = nn.Sequential(
nn.Linear(512 * 7 * 7, 4096),
nn.ReLU(True),
nn.Dropout(),
nn.Linear(4096, 4096),
nn.ReLU(True),
nn.Dropout(),
nn.Linear(4096, num_classes),
)
if init_weights:
self._initialize_weights()
def forward(self, x):
x = self.features(x)
x = self.avgpool(x)
x = torch.flatten(x, 1)
x = self.classifier(x)
return x
作为backbone时把dropout和最后一个全连接层去掉,取con5_3也就是最后一个卷积的输出作为rpn的输入。rpn+roi pooling的输出为7x7,正好又接上了原来的全连接层。
而rpn不同于后面的全连接层分类回归,rpn是全卷积网络,跟一个单类别(只分前景和背景)的单尺度检测的one-stage目标检测网络是一毛一样的。
转知乎:https://zhuanlan.zhihu.com/p/142866140?from_voters_page=true
友情链接:https://github.com/VectXmy/FasterRCNN.Pytorch