Pytorch搭建簡(jiǎn)單的卷積神經(jīng)網(wǎng)絡(luò)(CNN)實(shí)現(xiàn)MNIST數(shù)據(jù)集分類(lèi)任務(wù)
關(guān)于一些代碼里的解釋?zhuān)梢钥次疑弦黄l(fā)布的文章,里面有很詳細(xì)的介紹!?。?/h2>
可以依次把下面的代碼段合在一起運(yùn)行,也可以通過(guò)jupyter notebook分次運(yùn)行
第一步:基本庫(kù)的導(dǎo)入
import numpy as np import torch import torch.nn as nn import torchvision import torchvision.transforms as transforms from torch.utils.data import DataLoader import matplotlib.pyplot as plt import time np.random.seed(1234)
第二步:引用MNIST數(shù)據(jù)集,這里采用的是torchvision自帶的MNIST數(shù)據(jù)集
#這里用的是torchvision已經(jīng)封裝好的MINST數(shù)據(jù)集
trainset=torchvision.datasets.MNIST(
root='MNIST', #root是下載MNIST數(shù)據(jù)集保存的路徑,可以自行修改
train=True,
transform=torchvision.transforms.ToTensor(),
download=True
)
testset=torchvision.datasets.MNIST(
root='MNIST',
train=False,
transform=torchvision.transforms.ToTensor(),
download=True
)
trainloader = DataLoader(dataset=trainset, batch_size=100, shuffle=True) #DataLoader是一個(gè)很好地能夠幫助整理數(shù)據(jù)集的類(lèi),可以用來(lái)分批次,打亂以及多線程等操作
testloader = DataLoader(dataset=testset, batch_size=100, shuffle=True)下載之后利用DataLoader實(shí)例化為適合遍歷的訓(xùn)練集和測(cè)試集,我們把其中的某一批數(shù)據(jù)進(jìn)行可視化,下面是可視化的代碼,其實(shí)就是利用subplot畫(huà)了子圖。
#可視化某一批數(shù)據(jù)
train_img,train_label=next(iter(trainloader)) #iter迭代器,可以用來(lái)便利trainloader里面每一個(gè)數(shù)據(jù),這里只迭代一次來(lái)進(jìn)行可視化
fig, axes = plt.subplots(10, 10, figsize=(10, 10))
axes_list = []
#輸入到網(wǎng)絡(luò)的圖像
for i in range(axes.shape[0]):
for j in range(axes.shape[1]):
axes[i, j].imshow(train_img[i*10+j,0,:,:],cmap="gray") #這里畫(huà)出來(lái)的就是我們想輸入到網(wǎng)絡(luò)里訓(xùn)練的圖像,與之對(duì)應(yīng)的標(biāo)簽用來(lái)進(jìn)行最后分類(lèi)結(jié)果損失函數(shù)的計(jì)算
axes[i, j].axis("off")
#對(duì)應(yīng)的標(biāo)簽
print(train_label)

第三步:用pytorch搭建簡(jiǎn)單的卷積神經(jīng)網(wǎng)絡(luò)(CNN)
這里把卷積模塊單獨(dú)拿出來(lái)作為一個(gè)類(lèi),看上去會(huì)舒服一點(diǎn)。
#卷積模塊,由卷積核和激活函數(shù)組成
class conv_block(nn.Module):
def __init__(self,ks,ch_in,ch_out):
super(conv_block,self).__init__()
self.conv = nn.Sequential(
nn.Conv2d(ch_in, ch_out, kernel_size=ks,stride=1,padding=1,bias=True), #二維卷積核,用于提取局部的圖像信息
nn.ReLU(inplace=True), #這里用ReLU作為激活函數(shù)
nn.Conv2d(ch_out, ch_out, kernel_size=ks,stride=1,padding=1,bias=True),
nn.ReLU(inplace=True),
)
def forward(self,x):
return self.conv(x)下面是CNN主體部分,由上面的卷積模塊和全連接分類(lèi)器組合而成。這里只用了簡(jiǎn)單的幾個(gè)卷積塊進(jìn)行堆疊,沒(méi)有采用池化以及dropout的操作。主要目的是給大家簡(jiǎn)單搭建一下以便學(xué)習(xí)。
#常規(guī)CNN模塊(由幾個(gè)卷積模塊堆疊而成)
class CNN(nn.Module):
def __init__(self,kernel_size,in_ch,out_ch):
super(CNN, self).__init__()
feature_list = [16,32,64,128,256] #代表每一層網(wǎng)絡(luò)的特征數(shù),擴(kuò)大特征空間有助于挖掘更多的局部信息
self.conv1 = conv_block(kernel_size,in_ch,feature_list[0])
self.conv2 = conv_block(kernel_size,feature_list[0],feature_list[1])
self.conv3 = conv_block(kernel_size,feature_list[1],feature_list[2])
self.conv4 = conv_block(kernel_size,feature_list[2],feature_list[3])
self.conv5 = conv_block(kernel_size,feature_list[3],feature_list[4])
self.fc = nn.Sequential( #全連接層主要用來(lái)進(jìn)行分類(lèi),整合采集的局部信息以及全局信息
nn.Linear(feature_list[4] * 28 * 28, 1024), #此處28為MINST一張圖片的維度
nn.ReLU(),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Linear(512, 10)
)
def forward(self,x):
device = x.device
x1 = self.conv1(x )
x2 = self.conv2(x1)
x3 = self.conv3(x2)
x4 = self.conv4(x3)
x5 = self.conv5(x4)
x5 = x5.view(x5.size()[0], -1) #全連接層相當(dāng)于做了矩陣乘法,所以這里需要將維度降維來(lái)實(shí)現(xiàn)矩陣的運(yùn)算
out = self.fc(x5)
return out第四步:訓(xùn)練以及模型保存
先是一些網(wǎng)絡(luò)參數(shù)的定義,包括優(yōu)化器,迭代輪數(shù),學(xué)習(xí)率,運(yùn)行硬件等等的確定。
#網(wǎng)絡(luò)參數(shù)定義
device = torch.device("cuda:4") #此處根據(jù)電腦配置進(jìn)行選擇,如果沒(méi)有cuda就用cpu
#device = torch.device("cpu")
net = CNN(3,1,1).to(device = device,dtype = torch.float32)
epochs = 50 #訓(xùn)練輪次
optimizer = torch.optim.Adam(net.parameters(), lr=1e-4, weight_decay=1e-8) #使用Adam優(yōu)化器
criterion = nn.CrossEntropyLoss() #分類(lèi)任務(wù)常用的交叉熵?fù)p失函數(shù)
train_loss = []然后是每一輪訓(xùn)練的主體:
# Begin training
MinTrainLoss = 999
for epoch in range(1,epochs+1):
total_train_loss = []
net.train()
start = time.time()
for input_img,label in trainloader:
input_img = input_img.to(device = device,dtype=torch.float32) #我們同樣地,需要將我們?nèi)〕鰜?lái)的訓(xùn)練集數(shù)據(jù)進(jìn)行torch能夠運(yùn)算的格式轉(zhuǎn)換
label = label.to(device = device,dtype=torch.float32) #輸入和輸出的格式都保持一致才能進(jìn)行運(yùn)算
optimizer.zero_grad() #每一次算loss前需要將之前的梯度清零,這樣才不會(huì)影響后面的更新
pred_img = net(input_img)
loss = criterion(pred_img,label.long())
loss.backward()
optimizer.step()
total_train_loss.append(loss.item())
train_loss.append(np.mean(total_train_loss)) #將一個(gè)minibatch里面的損失取平均作為這一輪的loss
end = time.time()
#打印當(dāng)前的loss
print("epochs[%3d/%3d] current loss: %.5f, time: %.3f"%(epoch,epochs,train_loss[-1],(end-start))) #打印每一輪訓(xùn)練的結(jié)果
if train_loss[-1]<MinTrainLoss:
torch.save(net.state_dict(), "./model_min_train.pth") #保存loss最小的模型
MinTrainLoss = train_loss[-1]以下是迭代過(guò)程:

第五步:導(dǎo)入網(wǎng)絡(luò)模型,輸入某一批測(cè)試數(shù)據(jù),查看結(jié)果
我們先來(lái)看某一批測(cè)試數(shù)據(jù)
#測(cè)試機(jī)某一批數(shù)據(jù)
test_img,test_label=next(iter(testloader))
fig, axes = plt.subplots(10, 10, figsize=(10, 10))
axes_list = []
#輸入到網(wǎng)絡(luò)的圖像
for i in range(axes.shape[0]):
for j in range(axes.shape[1]):
axes[i, j].imshow(test_img[i*10+j,0,:,:],cmap="gray")
axes[i, j].axis("off")

然后將其輸入到訓(xùn)練好的模型進(jìn)行預(yù)測(cè)
#預(yù)測(cè)我拿出來(lái)的那一批數(shù)據(jù)進(jìn)行展示
cnn = CNN(3,1,1).to(device = device,dtype = torch.float32)
cnn.load_state_dict(torch.load("./model_min_train.pth", map_location=device)) #導(dǎo)入我們之前已經(jīng)訓(xùn)練好的模型
cnn.eval() #評(píng)估模式
test_img = test_img.to(device = device,dtype = torch.float32)
test_label = test_label.to(device = device,dtype = torch.float32)
pred_test = cnn(test_img) #記住,輸出的結(jié)果是一個(gè)長(zhǎng)度為10的tensor
test_pred = np.argmax(pred_test.cpu().data.numpy(), axis=1) #所以我們需要對(duì)其進(jìn)行最大值對(duì)應(yīng)索引的處理,從而得到我們想要的預(yù)測(cè)結(jié)果
#預(yù)測(cè)結(jié)果以及標(biāo)簽
print("預(yù)測(cè)結(jié)果")
print(test_pred)
print("標(biāo)簽")
print(test_label.cpu().data.numpy())
從預(yù)測(cè)的結(jié)果我們可以看到,整體上這么一個(gè)簡(jiǎn)單的CNN搭配全連接分類(lèi)器對(duì)MNIST這一批數(shù)據(jù)分類(lèi)的效果還不錯(cuò)。當(dāng)然,我這里只用了交叉熵?fù)p失函數(shù),并且沒(méi)有計(jì)算準(zhǔn)確率,僅供大家對(duì)于CNN學(xué)習(xí)和參考。
到此這篇關(guān)于Pytorch搭建簡(jiǎn)單的卷積神經(jīng)網(wǎng)絡(luò)(CNN)實(shí)現(xiàn)MNIST數(shù)據(jù)集分類(lèi)任務(wù)的文章就介紹到這了,更多相關(guān)Pytorch卷積神經(jīng)網(wǎng)絡(luò)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 對(duì)Pytorch神經(jīng)網(wǎng)絡(luò)初始化kaiming分布詳解
- Python使用numpy實(shí)現(xiàn)BP神經(jīng)網(wǎng)絡(luò)
- pytorch下使用LSTM神經(jīng)網(wǎng)絡(luò)寫(xiě)詩(shī)實(shí)例
- 基于MATLAB神經(jīng)網(wǎng)絡(luò)圖像識(shí)別的高識(shí)別率代碼
- 純用NumPy實(shí)現(xiàn)神經(jīng)網(wǎng)絡(luò)的示例代碼
- Python中LSTM回歸神經(jīng)網(wǎng)絡(luò)時(shí)間序列預(yù)測(cè)詳情
- Python基于numpy靈活定義神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)的方法
- Python利用全連接神經(jīng)網(wǎng)絡(luò)求解MNIST問(wèn)題詳解
- tensorflow學(xué)習(xí)筆記之mnist的卷積神經(jīng)網(wǎng)絡(luò)實(shí)例
- numpy實(shí)現(xiàn)神經(jīng)網(wǎng)絡(luò)反向傳播算法的步驟
- 如何在M芯片的Macbook上訓(xùn)練神經(jīng)網(wǎng)絡(luò)
相關(guān)文章
pytest生成Allure報(bào)告以及查看報(bào)告的實(shí)現(xiàn)
本文主要介紹了pytest生成Allure報(bào)告以及查看報(bào)告的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02
三種Matplotlib中動(dòng)態(tài)更新繪圖的方法總結(jié)
這篇文章主要為大家詳細(xì)介紹了如何隨著數(shù)據(jù)的變化動(dòng)態(tài)更新Matplotlib(Python的數(shù)據(jù)可視化庫(kù))圖,文中介紹了常用的三種方法,希望對(duì)大家有所幫助2024-04-04
使用EduBlock輕松學(xué)習(xí)Python編程
今天小編就為大家分享一篇關(guān)于使用EduBlock輕松學(xué)習(xí)Python編程的文章,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-10-10
利用20行Python 代碼實(shí)現(xiàn)加密通信
這篇文章主要介紹了利用Python 代碼實(shí)現(xiàn)加密通信,本文用 20 行 Python 代碼來(lái)演示加密、解密、簽名、驗(yàn)證的功能。大家依樣畫(huà)葫蘆,不僅能理解加密技術(shù),更能自己實(shí)現(xiàn)一套加密通信機(jī)制,需要的朋友可以參考一下2022-03-03
Django對(duì)接支付寶實(shí)現(xiàn)支付寶充值金幣功能示例
今天小編就為大家分享一篇Django對(duì)接支付寶實(shí)現(xiàn)支付寶充值金幣功能示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-12-12
Django?CSRF驗(yàn)證失敗請(qǐng)求被中斷的問(wèn)題
這篇文章主要介紹了Django?CSRF驗(yàn)證失敗請(qǐng)求被中斷的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09

