pytorch可视化实例:gradcam在resnet18上的应用(快餐式代码教程)
生活随笔
收集整理的這篇文章主要介紹了
pytorch可视化实例:gradcam在resnet18上的应用(快餐式代码教程)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
采用Grad-cam方法將神經網絡extractor的不同層進行可視化輸出,我的示例是將resnet18進行可視化。
代碼地址(百度網盤):resnet18_visual
提取碼:4ocv
resnet18:
- architecture
上圖是resnet18、resnet34、resnet50、resnet101、resnet152的結構圖。
從上圖能看出resnet的卷積部分主要分為4個模塊(在代碼中對應self.layer0~3)
代碼
在網絡中添加hook
class CamExtractor():"""Extracts cam features from the model"""def __init__(self, model):self.model = modelself.gradients = []def save_gradient(self, grad):self.gradients.append(grad)def forward_pass_on_convolutions(self, x):"""Does a forward pass on convolutions, hooks the function at given layer"""conv_output = []x = self.model.conv1(x)x = self.model.bn1(x)x = self.model.relu(x)x = self.model.maxpool(x)x = self.model.layer1(x)x.register_hook(self.save_gradient)conv_output.append(x) # Save the convolution output on that layerx = self.model.layer2(x)x.register_hook(self.save_gradient)conv_output.append(x)x = self.model.layer3(x)x.register_hook(self.save_gradient)conv_output.append(x)x = self.model.layer4(x)x.register_hook(self.save_gradient)conv_output.append(x)return conv_output, xdef forward_pass(self, x):"""Does a full forward pass on the model"""# Forward pass on the convolutionsconv_output, x = self.forward_pass_on_convolutions(x)x = self.model.avgpool(x)x = torch.flatten(x, 1)x = self.model.fc(x)return conv_output, x這部分代碼用于提取梯度值
查看源代碼,了解resnet類的結構,resnet有4層,梯度存儲在列表中輸出
forward_pass_on_convolutions中添加hook,存儲目標層的梯度值
Grad-cam
class GradCam():"""Produces class activation map"""def __init__(self, model):self.model = modelself.model.eval()# Define extractorself.extractor = CamExtractor(self.model)def generate_cam(self, input_image, target_layer, target_class=None):# Full forward pass# conv_output is the output of convolutions at specified layer# model_output is the final output of the model (1, 1000)conv_output, model_output = self.extractor.forward_pass(input_image)if target_class is None:target_class = np.argmax(model_output.data.numpy())# Target for backpropone_hot_output = torch.FloatTensor(1, model_output.size()[-1]).zero_()one_hot_output[0][target_class] = 1# Zero gradsself.model.zero_grad()# Backward pass with specified targetmodel_output.backward(gradient=one_hot_output, retain_graph=True)# Get hooked gradients,gradients# layer0:(1,512,7,7), layer1:(1,256,14,14), layer2:(1,128,28,28), layer3:(1,64,56,56),# 與后面conv_output是反的,因此需要逆序處理guided_gradients = self.extractor.gradients[-1 - target_layer].data.numpy()[0]# Get convolution outputs# layer0.shape:(64,56,56) layer1:(128,28,28) layer2:(256,14,14) layer3:(512,7,7)target = conv_output[target_layer].data.numpy()[0]# Get weights from gradientsweights = np.mean(guided_gradients, axis=(1, 2)) # Take averages for each gradient# Create empty numpy array for camcam = np.ones(target.shape[1:], dtype=np.float32)# Have a look at issue #11 to check why the above is np.ones and not np.zeros# Multiply each weight with its conv output and then, sumfor i, w in enumerate(weights):cam += w * target[i, :, :]cam = np.maximum(cam, 0)cam = (cam - np.min(cam)) / (np.max(cam) - np.min(cam)) # Normalize between 0-1cam = np.uint8(cam * 255) # Scale between 0-255 to visualizecam_resize = Image.fromarray(cam).resize((input_image.shape[2],input_image.shape[3]), Image.ANTIALIAS)cam = np.uint8(cam_resize) / 255return cam這部分依據梯度值生成熱圖
結果
第3層的輸出值結果最好,能比較好的將前景-背景區分開。
結束語
Grad-Cam是神經網絡比較經典的可視化方法,筆者僅用resnet18示例。
若讀者需要可視化自己的網絡,只需要修改CamExtractor類即可。
總結
以上是生活随笔為你收集整理的pytorch可视化实例:gradcam在resnet18上的应用(快餐式代码教程)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 台达触摸屏编程软件(Scredit)官方
- 下一篇: ESP32-CAM模块网络摄像头demo