总是遇到奇怪问题一

1.遇到报错ValueError: optimizer got an empty parameter list

在pycharm上也是报相同的错误

 

完整代码:

 1 import torch
 2 import torch.nn as nn
 3 from torch.optim import SGD
 4 import torch.utils.data as Data
 5 from sklearn.datasets import load_boston
 6 from sklearn.preprocessing import StandardScaler
 7 import pandas as pd
 8 import numpy as np
 9 import matplotlib.pyplot as plt
10 ##读取数据
11 boston_X,boston_y= load_boston(return_X_y=True)
12 print("boston_X.shape:",boston_X.shape)
13 plt.figure()
14 plt.hist(boston_y,bins=20)
15 plt.show()
16 ##数据标准化处理
17 ss = StandardScaler(with_mean=True,with_std=True)
18 boston_Xs= ss.fit_transform(boston_X)
19 ##将数据预处理为可以使用pytorch进行批量训练的形式
20 ##训练X转化为张量
21 train_xt= torch.from_numpy(boston_Xs.astype(np.float32))
22 ##训练集y转化为张量
23 train_yt = torch.from_numpy(boston_y.astype(np.float32))
24 ##将训练集转化为张量后,使用TensorDataset将X和Y整理到一起
25 train_data = Data.TensorDataset(train_xt,train_yt)
26 ##定义一个数据加载器,将训练数据集进行批量处理
27 train_loader = Data.DataLoader(
28     dataset = train_data,   ##使用的数据集
29     batch_size = 128,       ##批量处理样本的大小
30     shuffle = True,         ##每次迭代前打乱数据
31     num_workers = 1,        ##使用两个进程
32 )
33 ##使用继承Module的方式定义全连接神经网络
34 class MLPmodel(nn.Module):
35     def _init_(self):
36         super(MLPmodel,self)._init_()
37         ##定义第一个隐藏层
38         self.hidden1 = nn.Linear(
39             in_features = 13,   ##第一个隐藏层的输入,数据的特征数
40             out_feature = 10,   ##第一个隐藏层的输出,神经元的数量
41             bias = True,
42         )
43         self.activel = nn.ReLU()
44         ##定义第二个隐藏层
45         self.hidden2 = nn.Linear(10,10)
46         self.active2 = nn.ReLU()
47         ##定义预测回归层
48         self.regression = nn.Linear(10,1)
49     ##定义网络的前向传播路径
50     def forward(self, x):
51         x=self.hidden1(x)
52         x=self.active1(x)
53         x=self.hidden2(x)
54         x=self.active2(x)
55         output=self.regression(x)
56         ##输出为output
57         return output
58 ##输出网络结构
59 mlp1 = MLPmodel()
60 print(mlp1)
61 ##对回归模型mlp1进行训练并输出损失函数的变化情况,定义优化器和损失函数
62 optimizer = SGD(mlp1.parameters(),lr=0.001)
63 loss_func = nn.MSELoss()    ##最小均方根误差
64 train_loss_all = [ ]         ##输出每个批次训练的损失函数
65 ##进行训练,并输出每次迭代的损失函数
66 for epoch in range(30):
67     ##对训练数据的加载器进行迭代计算
68     for step,(b_x,b_y) in enumerate(train_loader):
69         output = mlp1(b_x).flatten()     ##MLP在训练batch上的输出
70         train_loss = loss_func(output,b_y)  ##均方根误差
71         optimizer.zero_grad()             ##每个迭代步的梯度初始化为0
72         train_loss.backward()             ##损失的向后传播,计算梯度
73         optimizer.step()                  ##使用梯度进行优化
74         train_loss_all.append(train_loss.item())
75 plt.figure()
76 plt.plot(train_loss_all,"r-")
77 plt.title("Train loss per iteration")
78 plt.show()
View Code

 解决:

在写_init_的时候左右边上一个下划线  _   ,因此报错,但实际需要使用的代码当中并非是这个函数,而是__init__  ,即左右两边是两个下划线
此错误为低级错误,缺花费了很多时间。


2.遇到错误
在运行以下代码时总是出错

heatmap = cv2.resize(heatmap, (img.shape[1], img.shape[0]))
AttributeError: 'NoneType' object has no attribute 'shape'

 

 原因可能是:当使用cv2的时候,1.图片不存在(路径不存在, 路径包含中文无法识别) 2.读取的图片内容和默认读取时参数匹配不匹配。(默认读取的是3通道的彩色图)例如读取到的图片是灰度图,就会返回None。

在我这个运行的代码当中,其中是第一种,其中路径包含了中文,因此报错,只需将中文切换为中文即可。

## 导入本章所需要的模块
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import requests
import cv2

import torch
from torch import nn
import torch.nn.functional as F
from torchvision import models
from torchvision import transforms
from PIL import Image

## 导入预训练好的VGG16网络
vgg16 = models.vgg16(pretrained=True)
print(vgg16)

## 读取一张图片,并对其进行可视化
im = Image.open("data/chap6/大象.jpg")
imarray = np.asarray(im) / 255.0
plt.figure()
plt.imshow(imarray)
plt.show()

imarray.shape

## 对一张图像处理为vgg16网络可以处理的形式
data_transforms = transforms.Compose([
    transforms.Resize((224,224)),# 重置图像分辨率
    transforms.ToTensor(),# 转化为张量并归一化至[0-1]
    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
input_im = data_transforms(im).unsqueeze(0)
print("input_im.shape:",input_im.shape)

## 使用钩子获取分类层的2个特征
## 定义一个辅助函数,来获取指定层名称的特征
activation = {} ## 保存不同层的输出
def get_activation(name):
    def hook(model, input, output):
        activation[name] = output.detach()
    return hook

## 获取中间的卷积后的图像特征
vgg16.eval()
##  第四层,经过第一次最大值池化
vgg16.features[4].register_forward_hook(get_activation("maxpool1"))
_ = vgg16(input_im)
maxpool1 = activation["maxpool1"]
print("获取特征的尺寸为:",maxpool1.shape)

## 对中间层进行可视化,可视化64个特征映射
plt.figure(figsize=(11,6))
for ii in range(maxpool1.shape[1]):
    ## 可视化每张手写体
    plt.subplot(6,11,ii+1)
    plt.imshow(maxpool1.data.numpy()[0,ii,:,:],cmap="gray")
    plt.axis("off")
plt.subplots_adjust(wspace=0.1, hspace=0.1)
plt.show()

## 获取更深层次的卷积后的图像特征
vgg16.eval()
vgg16.features[21].register_forward_hook(get_activation("layer21_conv"))
_ = vgg16(input_im)
layer21_conv = activation["layer21_conv"]
print("获取特征的尺寸为:",layer21_conv.shape)

## 对中间层进行可视化,只可视化前72个特征映射
plt.figure(figsize=(12,6))
for ii in range(72):
    ## 可视化每张手写体
    plt.subplot(6,12,ii+1)
    plt.imshow(layer21_conv.data.numpy()[0,ii,:,:],cmap="gray")
    plt.axis("off")
plt.subplots_adjust(wspace=0.1, hspace=0.1)
plt.show()

## 获取vgg模型训练时对应的1000类的类别标签
LABELS_URL = "https://s3.amazonaws.com/outcome-blog/imagenet/labels.json"
# 从网页链接中获取类别标签
response = requests.get(LABELS_URL)
labels = {int(key): value for key, value in response.json().items()}

## 使用VGG16网络预测图像的种类
vgg16.eval()
im_pre = vgg16(input_im)
## 计算预测top-5的可能性
softmax = nn.Softmax(dim=1)
im_pre_prob = softmax(im_pre)
prob,prelab = torch.topk(im_pre_prob,5)
prob = prob.data.numpy().flatten()
prelab = prelab.numpy().flatten()
for ii,lab in enumerate(prelab):
   print("index: ", lab ," label: ",labels[lab]," ||",prob[ii])

# African elephant 非洲大象
# tusker 长牙动物
# Indian elephant 印度象,亚洲象属maximus
# water buffalo 水牛
# Weimaraner 威马
## 定义一个萌购输出最后的卷机层输出和梯度的新的网络
class MyVgg16(nn.Module):
    def __init__(self):
        super(MyVgg16, self).__init__()

        # 使用预训练好的VGG16模型
        self.vgg = models.vgg16(pretrained=True)
        # 切分vgg6模型,便于获取卷积层的输出
        self.features_conv = self.vgg.features[:30]
        # 使用原始的最大值池化层
        self.max_pool = self.vgg.features[30]
        self.avgpool = self.vgg.avgpool
        # 使用vgg16的分类层
        self.classifier = self.vgg.classifier
        # 生成梯度占位符
        self.gradients = None

    # 获取地图的钩子函数
    def activations_hook(self, grad):
        self.gradients = grad

    def forward(self, x):
        x = self.features_conv(x)
        # 注册钩子
        h = x.register_hook(self.activations_hook)
        # 对卷积后的输出使用最大值池化
        x = self.max_pool(x)
        x = self.avgpool(x)
        x = x.view((1, -1))
        x = self.classifier(x)
        return x

    # 获取梯度的方法
    def get_activations_gradient(self):
        return self.gradients

    # 获取卷机层输出的方法
    def get_activations(self, x):
        return self.features_conv(x)


# 初始化网络
vggcam = MyVgg16()
# 设置网络的模式
vggcam.eval()
## 计算网络对图像的预测值
im_pre = vggcam(input_im)
## 计算预测top-5的可能性
softmax = nn.Softmax(dim=1)
im_pre_prob = softmax(im_pre)
prob, prelab = torch.topk(im_pre_prob, 5)
prob = prob.data.numpy().flatten()
prelab = prelab.numpy().flatten()
for ii, lab in enumerate(prelab):
    print("index: ", lab, " label: ", labels[lab], " ||", prob[ii])

## 这里预测结果和前面的一样,可能性最大的是第101个编号

# 获取相对于模型参数的输出梯度
im_pre[:, prelab[0]].backward()
# 获取模型的梯度
gradients = vggcam.get_activations_gradient()
# 计算梯度相应通道的均值
mean_gradients = torch.mean(gradients, dim=[0, 2, 3])
# 获取图像在相应卷积层输出的卷积特征
activations = vggcam.get_activations(input_im).detach()
# m每个通道乘以相应的梯度均值
for i in range(len(mean_gradients)):
    activations[:, i, :, :] *= mean_gradients[i]
# 计算所有通道的均值输出得到热力图
heatmap = torch.mean(activations, dim=1).squeeze()
# 使用relu函数作用于热力图
heatmap = F.relu(heatmap)
# 对热力图进行标准化
heatmap /= torch.max(heatmap)
heatmap = heatmap.numpy()
# 可视化热力图
plt.matshow(heatmap)

## 将Grad-CAM热力图融合到原始图像上
img = cv2.imread("data/chap6/aliphone.jpg")
#im = Image.open("data/chap6/大象.jpg")
print("大象img的尺寸为:",img.shape[1], img.shape[0])
heatmap = cv2.resize(heatmap, (img.shape[1], img.shape[0]))
heatmap = np.uint8(255 * heatmap)
heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
Grad_cam_img = heatmap * 0.4 + img
Grad_cam_img = Grad_cam_img / Grad_cam_img.max()
## 可视化图像
b,g,r = cv2.split(Grad_cam_img)
Grad_cam_img = cv2.merge([r,g,b])
plt.figure()
plt.imshow(Grad_cam_img)
plt.show()

## 可视化老虎图像的Grad-cam
im = Image.open("data/chap6/老虎.jpg")
input_im = data_transforms(im).unsqueeze(0)

# 初始化网络
vggcam = MyVgg16()
# 设置网络的模式
vggcam.eval()
## 计算网络对图像的预测值
im_pre = vggcam(input_im)
## 计算预测top-5的可能性
softmax = nn.Softmax(dim=1)
im_pre_prob = softmax(im_pre)
prob, prelab = torch.topk(im_pre_prob, 5)
prob = prob.data.numpy().flatten()
prelab = prelab.numpy().flatten()
for ii, lab in enumerate(prelab):
    print("index: ", lab, " label: ", labels[lab], " ||", prob[ii])

# 获取相对于模型参数的输出梯度
im_pre[:, prelab[0]].backward()
# 获取模型的梯度
gradients = vggcam.get_activations_gradient()
# 计算梯度相应通道的均值
mean_gradients = torch.mean(gradients, dim=[0, 2, 3])
# 获取图像在相应卷积层输出的卷积特征
activations = vggcam.get_activations(input_im).detach()
# m每个通道乘以相应的梯度均值
for i in range(len(mean_gradients)):
    activations[:, i, :, :] *= mean_gradients[i]
# 计算所有通道的均值输出得到热力图
heatmap = torch.mean(activations, dim=1).squeeze()
# 使用relu函数作用于热力图
heatmap = F.relu(heatmap)
# 对热力图进行标准化
heatmap /= torch.max(heatmap)
heatmap = heatmap.numpy()
# 可视化热力图
plt.matshow(heatmap)

## 将Grad-CAM热力图融合到原始图像上
img = cv2.imread("data/chap6/老虎.jpg")
heatmap = cv2.resize(heatmap, (img.shape[1], img.shape[0]))
heatmap = np.uint8(255 * heatmap)
heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
Grad_cam_img = heatmap * 0.5 + img
Grad_cam_img = Grad_cam_img / Grad_cam_img.max()
## 可视化图像
b, g, r = cv2.split(Grad_cam_img)
Grad_cam_img = cv2.merge([r, g, b])
plt.figure()
plt.imshow(Grad_cam_img)
plt.show()
View Code

 

posted @ 2020-11-07 20:53  兴财啊  阅读(1653)  评论(0编辑  收藏  举报