CNN 特征提取
CNN feature Extraction
class ResNet(nn.Module):
def __init__(self, output_features, fine_tuning=False):
super(ResNet, self).__init__()
self.resnet152 = tv.models.resnet152(pretrained=True)
#freezing the feature extraction layers
for param in self.resnet152.parameters():
param.requires_grad = fine_tuning
#self.features = self.resnet152.features
self.num_fts = 512
self.output_features = output_features
# Linear layer goes from 512 to 1024
self.classifier = nn.Linear(self.num_fts, self.output_features)
nn.init.xavier_uniform_(self.classifier.weight)
self.tanh = nn.Tanh()
def forward(self, x):
h = self.resnet152(x)
print('h: ',h.shape)
return h
image_model_resnet152=ResNet(output_features=10).to(device)
image_model_resnet152
在这里,在打印 image_model_resnet152
之后,我得到:
这里和(avgpool): Linear(in_features=2048)
有什么区别
和 (classifier): Linear(in_features=512)
?
我正在实施图像字幕模型,那么我应该 in_features
拍摄哪张图像?
ResNet 不像 VGG 那样简单:它不是顺序模型,即 forward
的定义中有一些特定于模型的逻辑 torchvision.models.resnet152
,例如,CNN 和分类器之间的特征扁平化。你可以看看its source code.
在这种情况下,最简单的做法是在 CNN 的最后一层添加一个钩子:layer4
,并将该层的结果记录在外部 dict。这是通过 register_forward_hook
.
完成的
定义钩子:
out = {}
def result(module, input, output):
out['layer4'] = output
在子模块上挂钩 resnet.layer4
:
>>> x = torch.rand(1,3,224,224)
>>> resnet = torchvision.models.resnet152()
>>> resnet.layer4.register_forward_hook(result)
推理后,您将可以访问 out
:
中的结果
>>> resnet(x)
>>> out['layer4']
(1, 2048, 7, 7)
你可以看看我的 another answer 更深入地使用 forward hooks。
一个可能的实现是:
class NN(nn.Module):
def __init__(self):
super().__init__()
self.resnet = torchvision.models.resnet152()
self.resnet.layer4.register_forward_hook(result)
self.out = {}
@staticmethod
def result(module, input, output):
out['layer4'] = output
def forward(self, x):
x = self.resnet(x)
return out['layer4']
然后您可以为自定义分类器定义附加层并在 forward
中调用它们。
class ResNet(nn.Module):
def __init__(self, output_features, fine_tuning=False):
super(ResNet, self).__init__()
self.resnet152 = tv.models.resnet152(pretrained=True)
#freezing the feature extraction layers
for param in self.resnet152.parameters():
param.requires_grad = fine_tuning
#self.features = self.resnet152.features
self.num_fts = 512
self.output_features = output_features
# Linear layer goes from 512 to 1024
self.classifier = nn.Linear(self.num_fts, self.output_features)
nn.init.xavier_uniform_(self.classifier.weight)
self.tanh = nn.Tanh()
def forward(self, x):
h = self.resnet152(x)
print('h: ',h.shape)
return h
image_model_resnet152=ResNet(output_features=10).to(device)
image_model_resnet152
在这里,在打印 image_model_resnet152
之后,我得到:
这里和(avgpool): Linear(in_features=2048)
有什么区别
和 (classifier): Linear(in_features=512)
?
我正在实施图像字幕模型,那么我应该 in_features
拍摄哪张图像?
ResNet 不像 VGG 那样简单:它不是顺序模型,即 forward
的定义中有一些特定于模型的逻辑 torchvision.models.resnet152
,例如,CNN 和分类器之间的特征扁平化。你可以看看its source code.
在这种情况下,最简单的做法是在 CNN 的最后一层添加一个钩子:layer4
,并将该层的结果记录在外部 dict。这是通过 register_forward_hook
.
定义钩子:
out = {}
def result(module, input, output):
out['layer4'] = output
在子模块上挂钩 resnet.layer4
:
>>> x = torch.rand(1,3,224,224)
>>> resnet = torchvision.models.resnet152()
>>> resnet.layer4.register_forward_hook(result)
推理后,您将可以访问 out
:
>>> resnet(x)
>>> out['layer4']
(1, 2048, 7, 7)
你可以看看我的 another answer 更深入地使用 forward hooks。
一个可能的实现是:
class NN(nn.Module):
def __init__(self):
super().__init__()
self.resnet = torchvision.models.resnet152()
self.resnet.layer4.register_forward_hook(result)
self.out = {}
@staticmethod
def result(module, input, output):
out['layer4'] = output
def forward(self, x):
x = self.resnet(x)
return out['layer4']
然后您可以为自定义分类器定义附加层并在 forward
中调用它们。