總是遇到奇怪問題一


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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM