Python深度學習基礎——卷積神經網絡(CNN)(PyTorch)

CNN原理

從DNN到CNN

  1. 卷積層與匯聚
  • 深度神經網絡DNN中,相鄰層的所有神經元之間都有連接,這叫全連接;卷積神經網絡 CNN 中,新增了卷積層(Convolution)與匯聚(Pooling)。
  • DNN 的全連接層對應 CNN 的卷積層,匯聚是與激活函數類似的附件;單個卷積層的結構是:卷積層-激活函數-(匯聚),其中匯聚可省略。

2.CNN:專攻多維數據
在深度神經網絡 DNN 課程的最后一章,使用 DNN 進行了手寫數字的識別。但是,圖像至少就有二維,向全連接層輸入時,需要多維數據拉平為 1 維數據,這樣一來,圖像的形狀就被忽視了,很多特征是隱藏在空間屬性里的,如下圖所示。
在這里插入圖片描述
而卷積層可以保持輸入數據的維數不變,當輸入數據是二維圖像時,卷積層會以多維數據的形式接收輸入數據,并同樣以多維數據的形式輸出至下一層,如下圖所示。
在這里插入圖片描述

卷積層

CNN 中的卷積層與 DNN 中的全連接層是平級關系,全連接層中的權重與偏置即y = ω1x1 + ω2x2 + ω3x3 + b中的 ω 與 b,卷積層中的權重與偏置變得稍微復雜。

  1. 內部參數:權重(卷積核)
    當輸入數據進入卷積層后,輸入數據會與卷積核進行卷積運算,如下圖:
    在這里插入圖片描述
    上圖中的輸入大小是(4,4),卷積核大小事(3,3),輸出大小是(2,2)卷積運算的原理是逐元素乘積后再相加。
    在這里插入圖片描述

  2. 內部參數:偏置
    在卷積運算的過程中也存在偏置,如下圖所示:
    在這里插入圖片描述

  3. 外部參數:補充
    為了防止經過多個卷積層后圖像越卷越小,可以在進行卷積層的處理之前,向輸入數據的周圍填入固定的數據(比如 0),這稱為填充(padding)。
    在這里插入圖片描述
    對上圖大小為(4, 4)的輸入數據應用了幅度為 1 的填充,填充值為 0。

  4. 外部參數:步幅
    使用卷積核的位置間隔被稱為步幅(stride),之前的例子中步幅都是 1,如果將步幅設為 2,此時使用卷積核的窗口的間隔變為 2。
    在這里插入圖片描述
    綜上,增大填充后,輸出尺寸會變大;而增大步幅后,輸出尺寸會變小

  5. 輸入與輸出尺寸的關系
    假設輸入尺寸為(H, W),卷積核的尺寸為(FH, FW),填充為 P,步幅為 S。則輸出尺寸(OH, OW)的計算公式為
    在這里插入圖片描述

多通道

在上一小節講的卷積層,僅僅針對二維的輸入與輸出數據(一般是灰度圖像),可稱之為單通道。
但是,彩色圖像除了高、長兩個維度之外,還有第三個維度:通道(channel)。例如,以 RGB 三原色為基礎的彩色圖像,其通道方向就有紅、黃、藍三部分,可視為 3 個單通道二維圖像的混合疊加。一般的,當輸入數據是二維時,權重被稱為卷積核(Kernel);當輸入數據是三維或更高時,權重被稱為濾波器(Filter)。

1.多通道輸入
對三維數據的卷積操作如圖 1-8 所示,輸入數據與濾波器的通道數必須要設為相同的值,可以發現,這種情況下的輸出結果降級為了二維
在這里插入圖片描述
將數據和濾波器看作長方體,如圖 1-9 所示
在這里插入圖片描述
C、H、W 是固定的順序,通道數要寫在高與寬的前面
圖 1-9 可看出,僅通過一個卷積層,三維就被降成二維了。大多數時候我們想讓三維的特征多經過幾個卷積層,因此就需要多通道輸出,如圖 1-10 所示。
在這里插入圖片描述
別忘了,卷積運算中存在偏置,如果進一步追加偏置的加法運算處理,則結果如圖 1-11 所示,每個通道都有一個單獨的偏置。
在這里插入圖片描述

匯聚(很多教材也叫做池化)

匯聚(Pooling)僅僅是從一定范圍內提取一個特征值,所以不存在要學習的內部參數。一般有平均匯聚與最大值匯聚。

  1. 平均匯聚
    一個以步幅為2進行的2*2窗口的平均匯聚,如圖1-12所示
    在這里插入圖片描述

  2. 最大值匯聚
    一個以步幅為 2 進行 2*2 窗口的最大值匯聚,如圖 1-13 所示
    在這里插入圖片描述
    匯聚對圖像的高 H 和寬 W 進行特征提取,不改變通道數 C。

尺寸變換總結

  1. 卷積層
    現假設卷積層的填充為P,步幅為S,由
  • 輸入數據的尺寸是:( C,H,W) 。
  • 濾波器的尺寸是:(FN,C,FH,FW)。
  • 輸出數據的尺寸是:(FN,OH,OW) 。

可得
在這里插入圖片描述
2. 匯聚
現假設匯聚的步幅為 S,由

  • 輸入數據的尺寸是:( C,H,W) 。
  • 輸出數據的尺寸是:(C,OH,OW) 。

可得
在這里插入圖片描述

LeNet-5

網絡結構

LeNet-5 雖誕生于 1998 年,但基于它的手寫數字識別系統則非常成功。
該網絡共 7 層,輸入圖像尺寸為 28×28,輸出則是 10 個神經元,分別表示某手寫數字是 0 至 9 的概率。
在這里插入圖片描述
PS:輸出層由 10 個徑向基函數 RBF 組成,用于歸一化最終的結果,目前RBF 已被 Softmax 取代。
根據網絡結構,在 PyTorch 的 nn.Sequential 中編寫為

self.net = nn.Sequential(nn.Conv2d(1, 6, kernel_size=5, padding=2), nn.Tanh(), # C1:卷積層nn.AvgPool2d(kernel_size=2, stride=2),                # S2:平均匯聚nn.Conv2d(6, 16, kernel_size=5), nn.Tanh(),           # C3:卷積層nn.AvgPool2d(kernel_size=2, stride=2),                # S4:平均匯聚nn.Conv2d(16, 120, kernel_size=5), nn.Tanh(),         # C5:卷積層nn.Flatten(),                                         # 把圖像鋪平成一維nn.Linear(120, 84), nn.Tanh(),                        # F5:全連接層nn.Linear(84, 10)                                     # F6:全連接層
)

其中,nn.Conv2d( )需要四個參數,分別為

  • in_channel:此層輸入圖像的通道數;
  • out_channel:此層輸出圖像的通道數;
  • kernel_size:卷積核尺寸;
  • padding:填充;
  • stride:步幅。

制作數據集

import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision import datasets
import matplotlib.pyplot as plt
%matplotlib inline
# 展示高清圖
from matplotlib_inline import backend_inline
backend_inline.set_matplotlib_formats('svg')
# 制作數據集
# 數據集轉換參數
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize(0.1307, 0.3081)
])
# 下載訓練集與測試集
train_Data = datasets.MNIST(root = 'D:/Jupyter/dataset/mnist/', # 下載路徑train = True, # 是 train 集download = True, # 如果該路徑沒有該數據集,就下載transform = transform # 數據集轉換參數
)
test_Data = datasets.MNIST(root = 'D:/Jupyter/dataset/mnist/', # 下載路徑train = False, # 是 test 集download = True, # 如果該路徑沒有該數據集,就下載transform = transform # 數據集轉換參數
)
# 批次加載器
train_loader = DataLoader(train_Data, shuffle=True, batch_size=256)
test_loader = DataLoader(test_Data, shuffle=False, batch_size=256)

搭建神經網絡

class CNN(nn.Module):def __init__(self):super(CNN,self).__init__()self.net = nn.Sequential(nn.Conv2d(1, 6, kernel_size=5, padding=2), nn.Tanh(),nn.AvgPool2d(kernel_size=2, stride=2),nn.Conv2d(6, 16, kernel_size=5), nn.Tanh(),nn.AvgPool2d(kernel_size=2, stride=2),nn.Conv2d(16, 120, kernel_size=5), nn.Tanh(),nn.Flatten(),nn.Linear(120, 84), nn.Tanh(),nn.Linear(84, 10))def forward(self, x):y = self.net(x)return y
# 查看網絡結構
X = torch.rand(size= (1, 1, 28, 28))
for layer in CNN().net:X = layer(X)print( layer.__class__.__name__, 'output shape: \t', X.shape )

在這里插入圖片描述

# 創建子類的實例,并搬到 GPU 上
model = CNN().to('cuda:0')

訓練網絡

# 損失函數的選擇
loss_fn = nn.CrossEntropyLoss() # 自帶 softmax 激活函數
# 優化算法的選擇
learning_rate = 0.9 # 設置學習率
optimizer = torch.optim.SGD(model.parameters(),lr = learning_rate,
)
# 訓練網絡
epochs = 5
losses = [] # 記錄損失函數變化的列表
for epoch in range(epochs):for (x, y) in train_loader: # 獲取小批次的 x 與 yx, y = x.to('cuda:0'), y.to('cuda:0')Pred = model(x) # 一次前向傳播(小批量)loss = loss_fn(Pred, y) # 計算損失函數losses.append(loss.item()) # 記錄損失函數的變化optimizer.zero_grad() # 清理上一輪滯留的梯度loss.backward() # 一次反向傳播optimizer.step() # 優化內部參數
Fig = plt.figure()
plt.plot(range(len(losses)), losses)
plt.show()

在這里插入圖片描述

測試網絡

# 測試網絡
correct = 0
total = 0
with torch.no_grad(): # 該局部關閉梯度計算功能for (x, y) in test_loader: # 獲取小批次的 x 與 yx, y = x.to('cuda:0'), y.to('cuda:0')Pred = model(x) # 一次前向傳播(小批量)_, predicted = torch.max(Pred.data, dim=1)correct += torch.sum( (predicted == y) )total += y.size(0) print(f'測試集精準度: {100*correct/total} %')   #OUT:測試集精準度: 9.569999694824219 %

AlexNet

網絡結構

AlexNet 是第一個現代深度卷積網絡模型,其首次使用了很多現代網絡的技術方法,作為 2012 年 ImageNet 圖像分類競賽冠軍,輸入為 3×224×224 的圖像,輸出為 1000 個類別的條件概率。
考慮到如果使用 ImageNet 訓練集會導致訓練時間過長,這里使用稍低億檔的 1×28×28 的 MNIST 數據集,并手動將其分辨率從 1×28×28 提到 1×224×224,同時輸出從 1000 個類別降到 10 個,修改后的網絡結構見下表。
在這里插入圖片描述
根據網絡結構,在 PyTorch 的 nn.Sequential 中編寫為

self.net = nn.Sequential(nn.Conv2d(1, 96, kernel_size=11, stride=4, padding=1), nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2),nn.Conv2d(96, 256, kernel_size=5, padding=2), nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2),nn.Conv2d(256, 384, kernel_size=3, padding=1), nn.ReLU(),nn.Conv2d(384, 384, kernel_size=3, padding=1), nn.ReLU(),nn.Conv2d(384, 256, kernel_size=3, padding=1), nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2),nn.Flatten(),nn.Linear(6400, 4096), nn.ReLU(),nn.Dropout(p=0.5), # Dropout——隨機丟棄權重nn.Linear(4096, 4096), nn.ReLU(),nn.Dropout(p=0.5), # 按概率 p 隨機丟棄突觸nn.Linear(4096, 10)
)

制作數據集

import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision import datasets
import matplotlib.pyplot as plt
%matplotlib inline
# 展示高清圖
from matplotlib_inline import backend_inline
backend_inline.set_matplotlib_formats('svg')
# 制作數據集
# 數據集轉換參數
transform = transforms.Compose([transforms.ToTensor(),transforms.Resize(224),transforms.Normalize(0.1307, 0.3081)
])
# 下載訓練集與測試集
train_Data = datasets.FashionMNIST(root = 'D:/Jupyter/dataset/mnist/',train = True,download = True,transform = transform
)
test_Data = datasets.FashionMNIST(root = 'D:/Jupyter/dataset/mnist/',train = False,download = True,transform = transform
)
# 批次加載器
train_loader = DataLoader(train_Data, shuffle=True, batch_size=128)
test_loader = DataLoader(test_Data, shuffle=False, batch_size=128)

搭建神經網絡

class CNN(nn.Module):def __init__(self):super(CNN,self).__init__()self.net = nn.Sequential(nn.Conv2d(1, 96, kernel_size=11, stride=4, padding=1),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2),nn.Conv2d(96, 256, kernel_size=5, padding=2),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2),nn.Conv2d(256, 384, kernel_size=3, padding=1),nn.ReLU(),nn.Conv2d(384, 384, kernel_size=3, padding=1),nn.ReLU(),nn.Conv2d(384, 256, kernel_size=3, padding=1),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2),nn.Flatten(),nn.Linear(6400, 4096), nn.ReLU(),nn.Dropout(p=0.5),nn.Linear(4096, 4096), nn.ReLU(),nn.Dropout(p=0.5),nn.Linear(4096, 10))def forward(self, x):y = self.net(x)return y
# 查看網絡結構
X = torch.rand(size= (1, 1, 224, 224))
for layer in CNN().net:X = layer(X)print( layer.__class__.__name__, 'output shape: \t', X.shape )

在這里插入圖片描述

# 創建子類的實例,并搬到 GPU 上
model = CNN().to('cuda:0')

訓練網絡

# 損失函數的選擇
loss_fn = nn.CrossEntropyLoss() # 自帶 softmax 激活函數
# 優化算法的選擇
learning_rate = 0.1 # 設置學習率
optimizer = torch.optim.SGD(model.parameters(),lr = learning_rate,
)
# 訓練網絡
epochs = 10
losses = [] # 記錄損失函數變化的列表
for epoch in range(epochs):for (x, y) in train_loader: # 獲取小批次的 x 與 yx, y = x.to('cuda:0'), y.to('cuda:0')Pred = model(x) # 一次前向傳播(小批量)loss = loss_fn(Pred, y) # 計算損失函數losses.append(loss.item()) # 記錄損失函數的變化optimizer.zero_grad() # 清理上一輪滯留的梯度loss.backward() # 一次反向傳播optimizer.step() # 優化內部參數
Fig = plt.figure()
plt.plot(range(len(losses)), losses)
plt.show()

測試網絡

# 測試網絡
correct = 0
total = 0
with torch.no_grad(): # 該局部關閉梯度計算功能for (x, y) in test_loader: # 獲取小批次的 x 與 yx, y = x.to('cuda:0'), y.to('cuda:0')Pred = model(x) # 一次前向傳播(小批量)_, predicted = torch.max(Pred.data, dim=1)correct += torch.sum( (predicted == y) )total += y.size(0)
print(f'測試集精準度: {100*correct/total} %')

GoogLeNet

網絡結構

2014 年,獲得 ImageNet 圖像分類競賽的冠軍是 GoogLeNet,其解決了一個重要問題:濾波器超參數選擇困難,如何能夠自動找到最佳的情況。
其在網絡中引入了一個小網絡——Inception 塊,由 4 條并行路徑組成,4 條路徑互不干擾。這樣一來,超參數最好的分支的那條分支,其權重會在訓練過程中不斷增加,這就類似于幫我們挑選最佳的超參數,如示例所示。

# 一個 Inception 塊
class Inception(nn.Module):def __init__(self, in_channels):super(Inception, self).__init__()self.branch1 = nn.Conv2d(in_channels, 16, kernel_size=1)self.branch2 = nn.Sequential(nn.Conv2d(in_channels, 16, kernel_size=1),nn.Conv2d(16, 24, kernel_size=3, padding=1),nn.Conv2d(24, 24, kernel_size=3, padding=1))self.branch3 = nn.Sequential(nn.Conv2d(in_channels, 16, kernel_size=1),nn.Conv2d(16, 24, kernel_size=5, padding=2))self.branch4 = nn.Conv2d(in_channels, 24, kernel_size=1)def forward(self, x):branch1 = self.branch1(x)branch2 = self.branch2(x)branch3 = self.branch3(x)branch4 = self.branch4(x)outputs = [branch1, branch2, branch3, branch4]return torch.cat(outputs, 1)

此外,分支 2 和分支 3 上增加了額外 1×1 的濾波器,這是為了減少通道數,降低模型復雜度。
GoogLeNet 之所以叫 GoogLeNet,是為了向 LeNet 致敬,其網絡結構為

class CNN(nn.Module):def __init__(self):super(CNN, self).__init__()self.net = nn.Sequential(nn.Conv2d(1, 10, kernel_size=5), nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2),Inception(in_channels=10),nn.Conv2d(88, 20, kernel_size=5), nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2),Inception(in_channels=20),nn.Flatten(),nn.Linear(1408, 10) )def forward(self, x):y = self.net(x)return y

制作數據集

import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision import datasets
import matplotlib.pyplot as plt
%matplotlib inline
# 展示高清圖
from matplotlib_inline import backend_inline
backend_inline.set_matplotlib_formats('svg')
# 制作數據集
# 數據集轉換參數
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize(0.1307, 0.3081)
])
# 下載訓練集與測試集
train_Data = datasets.FashionMNIST(root = 'D:/Jupyter/dataset/mnist/',train = True,download = True,transform = transform
)
test_Data = datasets.FashionMNIST(root = 'D:/Jupyter/dataset/mnist/',train = False,download = True,transform = transform
)
# 批次加載器
train_loader = DataLoader(train_Data, shuffle=True, batch_size=128)
test_loader = DataLoader(test_Data, shuffle=False, batch_size=128)

搭建神經網絡

# 一個 Inception 塊
class Inception(nn.Module):def __init__(self, in_channels):super(Inception, self).__init__()self.branch1 = nn.Conv2d(in_channels, 16, kernel_size=1)self.branch2 = nn.Sequential(nn.Conv2d(in_channels, 16, kernel_size=1),nn.Conv2d(16, 24, kernel_size=3, padding=1),nn.Conv2d(24, 24, kernel_size=3, padding=1))self.branch3 = nn.Sequential(nn.Conv2d(in_channels, 16, kernel_size=1),nn.Conv2d(16, 24, kernel_size=5, padding=2))self.branch4 = nn.Conv2d(in_channels, 24, kernel_size=1)def forward(self, x):branch1 = self.branch1(x)branch2 = self.branch2(x)branch3 = self.branch3(x)branch4 = self.branch4(x)outputs = [branch1, branch2, branch3, branch4]return torch.cat(outputs, 1)
class CNN(nn.Module):def __init__(self):super(CNN, self).__init__()self.net = nn.Sequential(nn.Conv2d(1, 10, kernel_size=5), nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2),Inception(in_channels=10),nn.Conv2d(88, 20, kernel_size=5), nn.ReLU(),nn.MaxPool2d(kernel_size=2, stride=2),Inception(in_channels=20),nn.Flatten(),nn.Linear(1408, 10))def forward(self, x):y = self.net(x) return y
# 查看網絡結構
X = torch.rand(size= (1, 1, 28, 28))
for layer in CNN().net:X = layer(X)print( layer.__class__.__name__, 'output shape: \t', X.shape )
# 創建子類的實例,并搬到 GPU 上
model = CNN().to('cuda:0')

訓練網絡

# 損失函數的選擇
loss_fn = nn.CrossEntropyLoss()
# 優化算法的選擇
learning_rate = 0.1 # 設置學習率
optimizer = torch.optim.SGD(model.parameters(),lr = learning_rate,
)
# 訓練網絡
epochs = 10
losses = [] # 記錄損失函數變化的列表
for epoch in range(epochs):for (x, y) in train_loader: # 獲取小批次的 x 與 yx, y = x.to('cuda:0'), y.to('cuda:0')Pred = model(x) # 一次前向傳播(小批量)loss = loss_fn(Pred, y) # 計算損失函數losses.append(loss.item()) # 記錄損失函數的變化optimizer.zero_grad() # 清理上一輪滯留的梯度loss.backward() # 一次反向傳播optimizer.step() # 優化內部參數
Fig = plt.figure()
plt.plot(range(len(losses)), losses)
plt.show()

測試網絡

# 測試網絡
correct = 0
total = 0
with torch.no_grad(): # 該局部關閉梯度計算功能for (x, y) in test_loader: # 獲取小批次的 x 與 yx, y = x.to('cuda:0'), y.to('cuda:0')Pred = model(x) # 一次前向傳播(小批量)_, predicted = torch.max(Pred.data, dim=1)correct += torch.sum( (predicted == y) )total += y.size(0)print(f'測試集精準度: {100*correct/total} %')

ResNet

網絡結構

殘差網絡(Residual Network,ResNet)榮獲 2015 年的 ImageNet 圖像分類競賽冠軍,其可以緩解深度神經網絡中增加深度帶來的“梯度消失”問題。
在反向傳播計算梯度時,梯度是不斷相乘的,假如訓練到后期,各層的梯度均小于 1,則其相乘起來就會不斷趨于 0。因此,深度學習的隱藏層并非越多越好,隱藏層越深,梯度越趨于 0,此之謂“梯度消失”。
在這里插入圖片描述

制作數據集

import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import transforms
from torchvision import datasets
import matplotlib.pyplot as plt
%matplotlib inline
# 展示高清圖
from matplotlib_inline import backend_inline
backend_inline.set_matplotlib_formats('svg')
# 制作數據集
# 數據集轉換參數
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize(0.1307, 0.3081)
])
# 下載訓練集與測試集
train_Data = datasets.FashionMNIST(root = 'D:/Jupyter/dataset/mnist/',train = True,download = True,transform = transform
)
test_Data = datasets.FashionMNIST(root = 'D:/Jupyter/dataset/mnist/',train = False,download = True,transform = transform
)
# 批次加載器
train_loader = DataLoader(train_Data, shuffle=True, batch_size=128)
test_loader = DataLoader(test_Data, shuffle=False, batch_size=128)

搭建神經網絡

# 殘差塊
class ResidualBlock(nn.Module):def __init__(self, channels):super(ResidualBlock, self).__init__()self.net = nn.Sequential(nn.Conv2d(channels, channels, kernel_size=3, padding=1),nn.ReLU(),nn.Conv2d(channels, channels, kernel_size=3, padding=1),)def forward(self, x):y = self.net(x)return nn.functional.relu(x+y)
class CNN(nn.Module):def __init__(self):super(CNN, self).__init__()self.net = nn.Sequential(nn.Conv2d(1, 16, kernel_size=5), nn.ReLU(),nn.MaxPool2d(2), ResidualBlock(16),nn.Conv2d(16, 32, kernel_size=5), nn.ReLU(),nn.MaxPool2d(2), ResidualBlock(32),nn.Flatten(),nn.Linear(512, 10))def forward(self, x):y = self.net(x) return y
# 查看網絡結構
X = torch.rand(size= (1, 1, 28, 28))for layer in CNN().net:X = layer(X)print( layer.__class__.__name__, 'output shape: \t', X.shape )
# 創建子類的實例,并搬到 GPU 上
model = CNN().to('cuda:0')

訓練網絡

# 損失函數的選擇
loss_fn = nn.CrossEntropyLoss()
# 優化算法的選擇
learning_rate = 0.1 # 設置學習率
optimizer = torch.optim.SGD(model.parameters(),lr = learning_rate,
)
# 訓練網絡
epochs = 10
losses = [] # 記錄損失函數變化的列表
for epoch in range(epochs):for (x, y) in train_loader: # 獲取小批次的 x 與 yx, y = x.to('cuda:0'), y.to('cuda:0')Pred = model(x) # 一次前向傳播(小批量)loss = loss_fn(Pred, y) # 計算損失函數losses.append(loss.item()) # 記錄損失函數的變化optimizer.zero_grad() # 清理上一輪滯留的梯度loss.backward() # 一次反向傳播optimizer.step() # 優化內部參數
Fig = plt.figure()
plt.plot(range(len(losses)), losses)
plt.show()

測試網絡

# 測試網絡
correct = 0
total = 0
with torch.no_grad(): # 該局部關閉梯度計算功能for (x, y) in test_loader: # 獲取小批次的 x 與 yx, y = x.to('cuda:0'), y.to('cuda:0')Pred = model(x) # 一次前向傳播(小批量)_, predicted = torch.max(Pred.data, dim=1)correct += torch.sum( (predicted == y) )total += y.size(0)
print(f'測試集精準度: {100*correct/total} %')

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/901191.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/901191.shtml
英文地址,請注明出處:http://en.pswp.cn/news/901191.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux 第三講 --- 基礎指令(三)

前言: 在前面我們已經講了有十幾個Linux的基礎指令,今天我們再補充幾個常用的基礎指令,為后面的學習做準備 。 目錄 前言: 一、兩個與時間相關的指令 1.date指令 演示 : 時間戳 設置時間 2、cal指令 演示&#x…

基于SiamFC的紅外目標跟蹤

基于SiamFC的紅外目標跟蹤 1,背景與原理2,SiamFC跟蹤方法概述2.1 核心思想2.2 算法優勢3,基于SiamFC的紅外跟蹤代碼詳解3.1 網絡定義與交叉相關模塊3.2 SiamFC 跟蹤器實現3.3 主程序:利用 OpenCV 實現視頻跟蹤4,總結與展望在紅外監控、無人機防御以及低光照場景中,紅外圖…

Odoo 部署本地 把現時的excel計算表格部署上odoo 教程

要將現有的 Excel 計算表格部署到 Odoo 平臺上,您可以按照以下步驟進行操作: 將 Excel 表格中的數據轉移到 Odoo 模塊中:首先,您需要將 Excel 表格中的數據導出為 CSV 格式,然后可以使用 Odoo 的數據導入功能將這些數據…

KWDB創作者計劃—KWDB認知引擎:數據流動架構與時空感知計算的范式突破

引言:數據智能的第三范式 在數字化轉型進入深水區的2025年,企業數據系統正面臨三重悖論:數據規模指數級增長與實時決策需求之間的矛盾、多模態數據孤島與業務連續性要求之間的沖突、靜態存儲范式與動態場景適配之間的鴻溝。KWDB(K…

C語言 數據結構 【棧】動態模擬實現

引言 動態模擬實現棧的各個接口 一、棧的概念與結構 棧:一種特殊的線性表,其只允許在固定的一端進行插入和刪除元素操作。進行數據插入和刪除操作的一端稱為棧頂,另一端稱為棧底。棧中的數據元素遵守后進先出LIFO(LastInFirstOut…

Python itertools模塊的groupby函數介紹

itertools.groupby 是 Python 標準庫 itertools 模塊中的一個函數,它的主要功能是對可迭代對象中相鄰的相同元素進行分組。 itertools.groupby(iterable, keyNone) 函數 作用: 將連續的(相鄰的)相同元素分組,返回 (…

Python實例題:使用Python生成分形圖片

目錄 Python實例題 題目 題目分析 需求理解 關鍵知識點 實現思路分析 代碼實現 代碼解釋 mandelbrot 函數: 設置復平面區域和圖像參數: 計算分形數據: 繪圖展示: 運行思路 Python實例題 題目 使用Python生成分形圖…

系統編程1(進程的概念與原理)

進程的概念與原理 計算機組成部分一般遵循馮諾依曼結構,也就是由控制器、運算器、存儲器、輸入設備、輸出設備五個部分組成。 ? 程序的編譯 一般在編寫出程序之后,并不能直接運行,而是需要把程序通過編譯器進行編譯,生成可執行…

《Vue Router實戰教程》5.嵌套路由

歡迎觀看《Vue Router 實戰(第4版)》視頻課程 嵌套路由 一些應用程序的 UI 由多層嵌套的組件組成。在這種情況下,URL 的片段通常對應于特定的嵌套組件結構,例如: 通過 Vue Router,你可以使用嵌套路由配置…

使用Python解決Logistic方程

引言 在數學和計算機科學中,Logistic 方程是描述人口增長、傳播過程等現象的一種常見模型。它通常用于表示一種有限資源下的增長過程,比如動物種群、疾病傳播等。本文將帶領大家通過 Python 實現 Logistic 方程的求解,幫助你更好地理解這一經典數學模型。 1.什么是 Logist…

《從零搭建Vue3項目實戰》(AI輔助搭建Vue3+ElemntPlus后臺管理項目)零基礎入門系列第十二篇(完結篇):數據統計功能實現

🤟致敬讀者 🟩感謝閱讀🟦笑口常開🟪生日快樂?早點睡覺 📘博主相關 🟧博主信息🟨博客首頁🟫專欄推薦🟥活動信息 文章目錄 《從零搭建Vue3項目實戰》(AI輔助…

研究嵌入式軟件架構時遇到的初始化堆棧溢出問題

文章目錄 2025年4月10日新增分析PC寄存器指針值排查問題map文件設計到的知識點1. **.bss 段(Block Started by Symbol)**2. **.data 段**3. **.text 段**4. **.heap 段**5. **.stack 段**6. **.rodata 段(只讀數據段)**7. **.init…

軟件架構評估兩大法:ATAM 和 SAAM 的對比與實踐

架構權衡分析方法(ATAM)和軟件架構分析方法(SAAM)是軟件架構評估領域中非常重要的兩種方法,以下為你詳細介紹: 一、架構權衡分析方法(ATAM) 1.背景與起源:ATAM 是由卡耐…

Python爬蟲-爬取全球股市漲跌幅和漲跌額數據

前言 本文是該專欄的第52篇,后面會持續分享python爬蟲干貨知識,記得關注。 本文中,筆者將基于Python爬蟲,實現批量采集全球股市行情(亞洲,美洲,歐非,其他等)的各股市“漲跌幅”以及“漲跌額”數據。 具體實現思路和詳細邏輯,筆者將在正文結合完整代碼進行詳細介紹。…

電流互感器的兩相星形接線的建模與仿真

微?“電擊小子程高興的MATLAB小屋”獲取巨額優惠 1.模型簡介 本仿真模型基于MATLAB/Simulink(版本MATLAB 2016Rb)軟件。建議采用matlab2016 Rb及以上版本打開。(若需要其他版本可聯系代為轉換) 2.仿真模型 3.仿真結果 3.1一次…

詳解 kotlin 相對 Java 特有的關鍵字及使用

文章目錄 1. val 和 var2. fun3. when4. is 和 !is5. lateinit6. by7. reified8. companion 本文首發地址:https://h89.cn/archives/366.html 最新更新地址:https://gitee.com/chenjim/chenjimblog Kotlin 在兼容Java的基礎上,引入了許多特有…

國標GB28181視頻平臺EasyCVR如何搭建汽車修理廠遠程視頻網絡監控方案

一、背景分析 近年我國汽車保有量持續攀升,與之相伴的汽車保養維修需求也逐漸提高。隨著社會經濟的發展,消費者對汽車維修服務質量的要求越來越高,這使得汽車維修店的安全防范與人員管理問題面臨著巨大挑戰。 多數汽車維修店分布分散&#…

linux RCU技術

RCU(Read-Copy-Update)是Linux內核中的一種同步機制,用于在多核處理器環境中實現無鎖讀取和延遲更新。Linux RCU(Read-Copy-Update)技術通過一種高效的同步機制來處理并發沖突,確保在多核環境中讀者和寫者對…

【筆記ing】AI大模型-02開發環境搭建

按實驗需求合理選用實例規格,一般:模型開發階段:使用最低算力2U8GB CPU。訓練或推理階段:切換至GPU規格,用完及時關閉算力環境,且切回最低算力規格。 每次實驗結束手動關閉實例。使用ModelArts公有云資源。…

Python——numpy測試題目

題目: 生成一個2行3列隨機整數二維數組a使用Numpy方法對(1)中數組a進行整體求積使用Numpy方法對(1)中數組a進行求每列最大值索引定義一個NumPy一維數組 b,元素為 1 到 10 的整數獲取(4&#x…