pytorch VGG11識(shí)別cifar10數(shù)據(jù)集(訓(xùn)練+預(yù)測(cè)單張輸入圖片操作)
首先這是VGG的結(jié)構(gòu)圖,VGG11則是紅色框里的結(jié)構(gòu),共分五個(gè)block,如紅框中的VGG11第一個(gè)block就是一個(gè)conv3-64卷積層:

一,寫VGG代碼時(shí),首先定義一個(gè) vgg_block(n,in,out)方法,用來構(gòu)建VGG中每個(gè)block中的卷積核和池化層:

n是這個(gè)block中卷積層的數(shù)目,in是輸入的通道數(shù),out是輸出的通道數(shù)
有了block以后,我們還需要一個(gè)方法把形成的block疊在一起,我們定義這個(gè)方法叫vgg_stack:
def vgg_stack(num_convs, channels): # vgg_net = vgg_stack((1, 1, 2, 2, 2), ((3, 64), (64, 128), (128, 256), (256, 512), (512, 512))) net = [] for n, c in zip(num_convs, channels): in_c = c[0] out_c = c[1] net.append(vgg_block(n, in_c, out_c)) return nn.Sequential(*net)
右邊的注釋
vgg_net = vgg_stack((1, 1, 2, 2, 2), ((3, 64), (64, 128), (128, 256), (256, 512), (512, 512)))
里,(1, 1, 2, 2, 2)表示五個(gè)block里,各自的卷積層數(shù)目,((3, 64), (64, 128), (128, 256), (256, 512), (512, 512))表示每個(gè)block中的卷積層的類型,如(3,64)表示這個(gè)卷積層輸入通道數(shù)是3,輸出通道數(shù)是64。vgg_stack方法返回的就是完整的vgg11模型了。
接著定義一個(gè)vgg類,包含vgg_stack方法:
#vgg類 class vgg(nn.Module): def __init__(self): super(vgg, self).__init__() self.feature = vgg_net self.fc = nn.Sequential( nn.Linear(512, 100), nn.ReLU(True), nn.Linear(100, 10) ) def forward(self, x): x = self.feature(x) x = x.view(x.shape[0], -1) x = self.fc(x) return x
最后:
net = vgg() #就能獲取到vgg網(wǎng)絡(luò)
那么構(gòu)建vgg網(wǎng)絡(luò)完整的pytorch代碼是:
def vgg_block(num_convs, in_channels, out_channels): net = [nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1), nn.ReLU(True)] for i in range(num_convs - 1): # 定義后面的許多層 net.append(nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1)) net.append(nn.ReLU(True)) net.append(nn.MaxPool2d(2, 2)) # 定義池化層 return nn.Sequential(*net) # 下面我們定義一個(gè)函數(shù)對(duì)這個(gè) vgg block 進(jìn)行堆疊 def vgg_stack(num_convs, channels): # vgg_net = vgg_stack((1, 1, 2, 2, 2), ((3, 64), (64, 128), (128, 256), (256, 512), (512, 512))) net = [] for n, c in zip(num_convs, channels): in_c = c[0] out_c = c[1] net.append(vgg_block(n, in_c, out_c)) return nn.Sequential(*net) #確定vgg的類型,是vgg11 還是vgg16還是vgg19 vgg_net = vgg_stack((1, 1, 2, 2, 2), ((3, 64), (64, 128), (128, 256), (256, 512), (512, 512))) #vgg類 class vgg(nn.Module): def __init__(self): super(vgg, self).__init__() self.feature = vgg_net self.fc = nn.Sequential( nn.Linear(512, 100), nn.ReLU(True), nn.Linear(100, 10) ) def forward(self, x): x = self.feature(x) x = x.view(x.shape[0], -1) x = self.fc(x) return x #獲取vgg網(wǎng)絡(luò) net = vgg()
基于VGG11的cifar10訓(xùn)練代碼:
import sys
import numpy as np
import torch
from torch import nn
from torch.autograd import Variable
from torchvision.datasets import CIFAR10
import torchvision.transforms as transforms
def vgg_block(num_convs, in_channels, out_channels):
net = [nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1), nn.ReLU(True)]
for i in range(num_convs - 1): # 定義后面的許多層
net.append(nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1))
net.append(nn.ReLU(True))
net.append(nn.MaxPool2d(2, 2)) # 定義池化層
return nn.Sequential(*net)
# 下面我們定義一個(gè)函數(shù)對(duì)這個(gè) vgg block 進(jìn)行堆疊
def vgg_stack(num_convs, channels): # vgg_net = vgg_stack((1, 1, 2, 2, 2), ((3, 64), (64, 128), (128, 256), (256, 512), (512, 512)))
net = []
for n, c in zip(num_convs, channels):
in_c = c[0]
out_c = c[1]
net.append(vgg_block(n, in_c, out_c))
return nn.Sequential(*net)
#vgg類
class vgg(nn.Module):
def __init__(self):
super(vgg, self).__init__()
self.feature = vgg_net
self.fc = nn.Sequential(
nn.Linear(512, 100),
nn.ReLU(True),
nn.Linear(100, 10)
)
def forward(self, x):
x = self.feature(x)
x = x.view(x.shape[0], -1)
x = self.fc(x)
return x
# 然后我們可以訓(xùn)練我們的模型看看在 cifar10 上的效果
def data_tf(x):
x = np.array(x, dtype='float32') / 255
x = (x - 0.5) / 0.5
x = x.transpose((2, 0, 1)) ## 將 channel 放到第一維,只是 pytorch 要求的輸入方式
x = torch.from_numpy(x)
return x
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5)),
])
def get_acc(output, label):
total = output.shape[0]
_, pred_label = output.max(1)
num_correct = (pred_label == label).sum().item()
return num_correct / total
def train(net, train_data, valid_data, num_epochs, optimizer, criterion):
if torch.cuda.is_available():
net = net.cuda()
for epoch in range(num_epochs):
train_loss = 0
train_acc = 0
net = net.train()
for im, label in train_data:
if torch.cuda.is_available():
im = Variable(im.cuda())
label = Variable(label.cuda())
else:
im = Variable(im)
label = Variable(label)
# forward
output = net(im)
loss = criterion(output, label)
# forward
optimizer.zero_grad()
loss.backward()
optimizer.step()
train_loss += loss.item()
train_acc += get_acc(output, label)
if valid_data is not None:
valid_loss = 0
valid_acc = 0
net = net.eval()
for im, label in valid_data:
if torch.cuda.is_available():
with torch.no_grad():
im = Variable(im.cuda())
label = Variable(label.cuda())
else:
with torch.no_grad():
im = Variable(im)
label = Variable(label)
output = net(im)
loss = criterion(output, label)
valid_loss += loss.item()
valid_acc += get_acc(output, label)
epoch_str = (
"Epoch %d. Train Loss: %f, Train Acc: %f, Valid Loss: %f, Valid Acc: %f, "
% (epoch, train_loss / len(train_data),
train_acc / len(train_data), valid_loss / len(valid_data),
valid_acc / len(valid_data)))
else:
epoch_str = ("Epoch %d. Train Loss: %f, Train Acc: %f, " %
(epoch, train_loss / len(train_data),
train_acc / len(train_data)))
# prev_time = cur_time
print(epoch_str)
if __name__ == '__main__':
# 作為實(shí)例,我們定義一個(gè)稍微簡單一點(diǎn)的 vgg11 結(jié)構(gòu),其中有 8 個(gè)卷積層
vgg_net = vgg_stack((1, 1, 2, 2, 2), ((3, 64), (64, 128), (128, 256), (256, 512), (512, 512)))
print(vgg_net)
train_set = CIFAR10('./data', train=True, transform=transform, download=True)
train_data = torch.utils.data.DataLoader(train_set, batch_size=64, shuffle=True)
test_set = CIFAR10('./data', train=False, transform=transform, download=True)
test_data = torch.utils.data.DataLoader(test_set, batch_size=128, shuffle=False)
net = vgg()
optimizer = torch.optim.SGD(net.parameters(), lr=1e-1)
criterion = nn.CrossEntropyLoss() #損失函數(shù)為交叉熵
train(net, train_data, test_data, 50, optimizer, criterion)
torch.save(net, 'vgg_model.pth')
結(jié)束后,會(huì)出現(xiàn)一個(gè)模型文件vgg_model.pth
二,然后網(wǎng)上找張圖片,把圖片縮成32x32,放到預(yù)測(cè)代碼中,即可有預(yù)測(cè)結(jié)果出現(xiàn),預(yù)測(cè)代碼如下:
import torch
import cv2
import torch.nn.functional as F
from vgg2 import vgg ##重要,雖然顯示灰色(即在次代碼中沒用到),但若沒有引入這個(gè)模型代碼,加載模型時(shí)會(huì)找不到模型
from torch.autograd import Variable
from torchvision import datasets, transforms
import numpy as np
classes = ('plane', 'car', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
if __name__ == '__main__':
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = torch.load('vgg_model.pth') # 加載模型
model = model.to(device)
model.eval() # 把模型轉(zhuǎn)為test模式
img = cv2.imread("horse.jpg") # 讀取要預(yù)測(cè)的圖片
trans = transforms.Compose(
[
transforms.ToTensor(),
transforms.Normalize(mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5))
])
img = trans(img)
img = img.to(device)
img = img.unsqueeze(0) # 圖片擴(kuò)展多一維,因?yàn)檩斎氲奖4娴哪P椭惺?維的[batch_size,通道,長,寬],而普通圖片只有三維,[通道,長,寬]
# 擴(kuò)展后,為[1,1,28,28]
output = model(img)
prob = F.softmax(output,dim=1) #prob是10個(gè)分類的概率
print(prob)
value, predicted = torch.max(output.data, 1)
print(predicted.item())
print(value)
pred_class = classes[predicted.item()]
print(pred_class)
# prob = F.softmax(output, dim=1)
# prob = Variable(prob)
# prob = prob.cpu().numpy() # 用GPU的數(shù)據(jù)訓(xùn)練的模型保存的參數(shù)都是gpu形式的,要顯示則先要轉(zhuǎn)回cpu,再轉(zhuǎn)回numpy模式
# print(prob) # prob是10個(gè)分類的概率
# pred = np.argmax(prob) # 選出概率最大的一個(gè)
# # print(pred)
# # print(pred.item())
# pred_class = classes[pred]
# print(pred_class)
縮成32x32的圖片:

運(yùn)行結(jié)果:

以上這篇pytorch VGG11識(shí)別cifar10數(shù)據(jù)集(訓(xùn)練+預(yù)測(cè)單張輸入圖片操作)就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
python3.4 將16進(jìn)制轉(zhuǎn)成字符串的實(shí)例
今天小編就為大家分享一篇python3.4 將16進(jìn)制轉(zhuǎn)成字符串的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-06-06
python 中 .py文件 轉(zhuǎn) .pyd文件的操作
這篇文章主要介紹了python 中 .py文件 轉(zhuǎn) .pyd文件的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-03-03
python nmap實(shí)現(xiàn)端口掃描器教程
這篇文章主要為大家詳細(xì)介紹了python nmap實(shí)現(xiàn)端口掃描器教程,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08
pandas讀取excel,txt,csv,pkl文件等命令的操作
這篇文章主要介紹了pandas讀取excel,txt,csv,pkl文件等命令的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-03-03
選擇python進(jìn)行數(shù)據(jù)分析的理由和優(yōu)勢(shì)
在本篇文章中小編給大家整理了關(guān)于選擇python進(jìn)行數(shù)據(jù)分析的理由和優(yōu)勢(shì),對(duì)此有需要的朋友們可以跟著學(xué)習(xí)參考下。2019-06-06
深入探討Python復(fù)合型數(shù)據(jù)的常見陷阱與避免方法
在Python中,復(fù)合型數(shù)據(jù)(例如列表、元組、集合和字典)是非常常用的數(shù)據(jù)類型,本文將深入探討Python復(fù)合型數(shù)據(jù)的常見陷阱,并提供一些避免這些問題的實(shí)用建議和技巧,希望對(duì)大家有所幫助2024-03-03

