KeyError:'conv4_2'时发现样式丢失函数和内容丢失函数的丢失



在为"基于Pytorch(深度学习)的神经风格迁移我试图找到内容丢失和风格丢失,但在代码的实现过程中,我遇到了一个KeyError: 'conv4_2',我无法解决。

请看下面的代码:

# Get content, style features and create gram matrix 
def get_features(image,model):
layers = { 
'0' : 'conv1_1',
'5' : 'conv2_1',
'10' : 'conv3_1',
'19' : 'conv4_1',
'21' : 'conv4_2', # content_feature
'28' : 'conv5_1'
}
x  = image 

Features = {}
for name, layer in model._modules.items():
x = layer(x)
if name in layers:
Features[layers[name]] = x
return Features
content_f = get_features(content_p,vgg)
style_f = get_features(style_p,vgg)
def gram_matrix(tensor):
b,c,h,w = tensor.size()
tensor = tensor.view(c,h*w)
gram = torch.mm(tensor,tensor.t())
return gram 
style_grams = {layer: gram_matrix(style_f[layer]) for layer in style_f}
# Creating Style and Content loss fucntion
def content_loss(target_conv4_2, content_conv4_2):
loss = torch.mean((target_conv4_2-content_conv4_2)**2)
return loss
style_weights = {
'conv1_1' : 1.0,
'conv2_1' : 0.75,
'conv3_1' : 0.2,
'conv4_1' : 0.2,
'conv5_1' : 0.2
}
def style_loss(style_weights,target_features,style_grams):
loss = 0
for layer in style_weights:
target_f = target_features[layer]
target_gram = gram_matrix(target_f)
style_gram = style_gram[layer]
b,c,h,w = target_f.shape 
layer_loss = style_weights[layers]*torch.mean((target_gram-style_gram)**2)
loss += layer_loss/(c*h*w)
return loss
target = content_p.clone().requires_grad_(True).to(device)
target_f = get_features(target,vgg)

print("Content Loss : ",content_loss(target_f['conv4_2'],content_f['conv4_2']))
print("Style Loss : ",style_loss(style_weights, target_f , style_grams))

最后2行代码输出:

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-22-3b32a5406c6a> in <module>()
----> 1 print("Content Loss : ",content_loss(target_f['conv4_2'],content_f['conv4_2']))
2 print("Style Loss : ",style_loss(style_weights, target_f , style_grams))
KeyError: 'conv4_2'

我将非常感谢您的快速回复!!请让我知道,如果有人需要任何代码相关的帮助来解决这个问题!

假设您正在使用标准的torchvisionVGG网络,如:

>>> vgg = torchvision.models.vgg16()

你想在get_features函数中访问一些卷积层。然而,这些层包含在一个子模块内,而不是直接的子模块(您正在访问的_modules属性)。顺便说一句,你不应该使用这个属性,下划线是用来指定私有属性的。

>>> dict(vgg.named_children()).keys()
dict_keys(['features', 'avgpool', 'classifier'])

所以在这里,您应该查看vgg.features即。VGG的CNN部分。

那么在这一点上,你的函数是有意义的,因为你是从模型的卷积部分的层数索引:

def get_features(x, model):
layers = {'0' : 'conv1_1',
'5' : 'conv2_1',
'10': 'conv3_1',
'19': 'conv4_1',
'21': 'conv4_2',
'28': 'conv5_1'}
features = {}
for name, layer in model.named_children():
x = layer(x)
if name in layers:
features[layers[name]] = x.detach()
return features

features将包含以下键:

>>> features.keys()
dict_keys(['conv1_1', 'conv2_1', 'conv3_1', 'conv4_1', 'conv4_2', 'conv5_1'])

或者,你可以使用向前钩子,这在我看来是一个更好的解决方案。在这个答案中,我将详细解释如何实现这样一个方法。

相关内容

最新更新