我正在尝试使用此模块(https://github.com/utkuozbulak/pytorch-cnn-visualizations)来可视化网络在我的图像中所看到的内容,并且我对其进行了一些编辑以满足我的需要。但是,出现错误,我无法解决此问题。 (AttributeError:“ GoogLeNet”对象没有属性“ features”)
最初,该模块使用misc_functions.py脚本处理图像(获取RGB,转换为灰度,调整大小等),但是由于我使用的网络已经完成了这些操作,因此我对该模块进行了一些编辑,以便它不使用这些功能。
在下面,您可以找到我正在尝试使用的代码以及我曾经训练过的网络
"""
Created on Thu Oct 26 11:19:58 2017
@author: Utku Ozbulak - github.com/utkuozbulak
"""
import os
import time
import matplotlib.pyplot as plt
import numpy as np
import torch
import torch.optim as optim
from torch import nn
import torchvision
from torch.utils.data import DataLoader, random_split
from torchvision.datasets import ImageFolder
from torchvision import transforms
from torchvision import models
from PIL import Image
from misc_functions import save_gradient_images
class VanillaBackprop():
"""
Produces gradients generated with vanilla back propagation from the image
"""
def __init__(self, model):
self.model = model
self.gradients = None
# Put model in evaluation mode
self.model.eval()
# Hook the first layer to get the gradient
self.hook_layers()
def hook_layers(self):
def hook_function(module, grad_in, grad_out):
self.gradients = grad_in[0]
# Register hook to the first layer
first_layer = list(self.model.features._modules.items())[0][1]
first_layer.register_backward_hook(hook_function)
def generate_gradients(self, input_image, target_class):
# Forward
model_output = self.model(input_image)
# Zero grads
self.model.zero_grad()
# Target for backprop
one_hot_output = torch.FloatTensor(1, model_output.size()[-1]).zero_()
one_hot_output[0][target_class] = 1
# Backward pass
model_output.backward(gradient=one_hot_output)
# Convert Pytorch variable to numpy array
# [0] to get rid of the first channel (1,3,224,224)
gradients_as_arr = self.gradients.data.numpy()[0]
return gradients_as_arr
#Use simple pre-trained ResNet
net = models.googlenet(pretrained=True)
#manually replace last layer for different num_classes (necessary for pretrained models)
net.fc = torch.nn.Linear(net.fc.in_features, 4)
#to gpu
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
net = net.to(device)
net.load_state_dict(torch.load("/home/serce/scratch/titan_googlenet_epoch_100.pt")["model_state_dict"])
net.eval()
# dataLoader with transforms
tr = transforms.Compose([
transforms.Resize((224, 224)),
transforms.RandomHorizontalFlip(),
transforms.RandomVerticalFlip(),
transforms.ToTensor()
])
ds = ImageFolder('/scratch/serce/chromatin_texture/dna_sir160-163_128/sted/', transform=tr)
def get_example_params(example_index):
"""
Gets used variables for almost all visualizations, like the image, model etc.
Args:
example_index (int): Image id to use from examples
returns:
original_image (numpy arr): Original image read from the file
prep_img (numpy_arr): Processed image
target_class (int): Target class for the image
file_name_to_export (string): File name to export the visualizations
pretrained_model(Pytorch model): Model to use for the operations
"""
# Pick one of the examples
img_path = ds[example_index][0]
target_class = ds[example_index][1]
file_name_to_export = "example{}".format(example_index)
# Read image
original_image = img_path
# Process image
prep_img = original_image
# Define model
pretrained_model = net
return (original_image,
prep_img,
target_class,
file_name_to_export,
pretrained_model)
if __name__ == '__main__':
# Get params
target_example = 0
(original_image, prep_img, target_class, file_name_to_export, pretrained_model) =\
get_example_params(target_example)
# Vanilla backprop
VBP = VanillaBackprop(pretrained_model)
# Generate gradients
vanilla_grads = VBP.generate_gradients(prep_img, target_class)
# Save colored gradients
save_gradient_images(vanilla_grads, file_name_to_export + '_Vanilla_BP_color')
# Convert to grayscale
grayscale_vanilla_grads = vanilla_grads
# Save grayscale gradients
save_gradient_images(grayscale_vanilla_grads, file_name_to_export + '_Vanilla_BP_gray')
print('Vanilla backprop completed')
我不知道输出应该是什么样子,但是我正在尝试获取原始图片的图像,并查看神经网络看到的图像。
答案 0 :(得分:0)
我已经检查了torchvision.models提供的GoogleNet的源代码。它没有名为features
的属性。我想您会发现具有features
属性的VGG。如果要提取从GoogleNet提取的功能,则可能需要编写包装器。
一个简单的例子。
import torch
import torch.nn as nn
import torchvision.models as models
class FeatureExtractor(nn.Module):
def __init__(self):
super(FeatureExtractor, self).__init__()
self.net = models.googlenet(pretrained=True)
# If you treat GooLeNet as a fixed feature extractor, disable the gradients and save some memory
for p in self.net.parameters():
p.requires_grad = False
# Define which layers you are going to extract
self.features = nn.Sequential(*list(self.net.children())[:4])
def forward(self, x):
return self.features(x)
if __name__ == "__main__":
fe = FeatureExtractor()
noise = torch.randn(1, 3, 224, 224)
feat = fe(noise)
#print(feat)