pytorch VGG11识别cifar10数据集(训练+预测单张输入图片操作)


Posted in Python onJune 24, 2020

首先这是VGG的结构图,VGG11则是红色框里的结构,共分五个block,如红框中的VGG11第一个block就是一个conv3-64卷积层:

pytorch VGG11识别cifar10数据集(训练+预测单张输入图片操作)

一,写VGG代码时,首先定义一个 vgg_block(n,in,out)方法,用来构建VGG中每个block中的卷积核和池化层:

pytorch VGG11识别cifar10数据集(训练+预测单张输入图片操作)

n是这个block中卷积层的数目,in是输入的通道数,out是输出的通道数

有了block以后,我们还需要一个方法把形成的block叠在一起,我们定义这个方法叫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)表示五个block里,各自的卷积层数目,((3, 64), (64, 128), (128, 256), (256, 512), (512, 512))表示每个block中的卷积层的类型,如(3,64)表示这个卷积层输入通道数是3,输出通道数是64。vgg_stack方法返回的就是完整的vgg11模型了。

接着定义一个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网络

那么构建vgg网络完整的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)
 
# 下面我们定义一个函数对这个 vgg block 进行堆叠
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网络
net = vgg()

基于VGG11的cifar10训练代码:

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)
 
# 下面我们定义一个函数对这个 vgg block 进行堆叠
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
 
# 然后我们可以训练我们的模型看看在 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__':
 # 作为实例,我们定义一个稍微简单一点的 vgg11 结构,其中有 8 个卷积层
 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() #损失函数为交叉熵
 
 train(net, train_data, test_data, 50, optimizer, criterion)
 torch.save(net, 'vgg_model.pth')

结束后,会出现一个模型文件vgg_model.pth

二,然后网上找张图片,把图片缩成32x32,放到预测代码中,即可有预测结果出现,预测代码如下:

import torch
import cv2
import torch.nn.functional as F
from vgg2 import vgg ##重要,虽然显示灰色(即在次代码中没用到),但若没有引入这个模型代码,加载模型时会找不到模型
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() # 把模型转为test模式
 
 img = cv2.imread("horse.jpg") # 读取要预测的图片
 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) # 图片扩展多一维,因为输入到保存的模型中是4维的[batch_size,通道,长,宽],而普通图片只有三维,[通道,长,宽]
 # 扩展后,为[1,1,28,28]
 output = model(img)
 prob = F.softmax(output,dim=1) #prob是10个分类的概率
 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的数据训练的模型保存的参数都是gpu形式的,要显示则先要转回cpu,再转回numpy模式
 # print(prob) # prob是10个分类的概率
 # pred = np.argmax(prob) # 选出概率最大的一个
 # # print(pred)
 # # print(pred.item())
 # pred_class = classes[pred]
 # print(pred_class)

缩成32x32的图片:

pytorch VGG11识别cifar10数据集(训练+预测单张输入图片操作)

运行结果:

pytorch VGG11识别cifar10数据集(训练+预测单张输入图片操作)

以上这篇pytorch VGG11识别cifar10数据集(训练+预测单张输入图片操作)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现文件名批量替换和内容替换
Mar 20 Python
在Django的URLconf中使用命名组的方法
Jul 18 Python
Python 专题三 字符串的基础知识
Mar 19 Python
python实现闹钟定时播放音乐功能
Jan 25 Python
Python MySQLdb 使用utf-8 编码插入中文数据问题
Mar 13 Python
pandas表连接 索引上的合并方法
Jun 08 Python
python一键去抖音视频水印工具
Sep 14 Python
Python Pandas中根据列的值选取多行数据
Jul 08 Python
解决Django中多条件查询的问题
Jul 18 Python
Python类中方法getitem和getattr详解
Aug 30 Python
python 爬取古诗文存入mysql数据库的方法
Jan 08 Python
python ConfigParser库的使用及遇到的坑
Feb 12 Python
Python Tornado核心及相关原理详解
Jun 24 #Python
如何使用Python处理HDF格式数据及可视化问题
Jun 24 #Python
pytorch SENet实现案例
Jun 24 #Python
利用PyTorch实现VGG16教程
Jun 24 #Python
python安装读取grib库总结(推荐)
Jun 24 #Python
Pytorch mask-rcnn 实现细节分享
Jun 24 #Python
在Pytorch中使用Mask R-CNN进行实例分割操作
Jun 24 #Python
You might like
PHP求最大子序列和的算法实现
2011/06/24 PHP
php中error与exception的区别及应用
2014/07/28 PHP
yii2中dropDownList实现二级和三级联动写法
2017/04/26 PHP
javascript form 验证函数 弹出对话框形式
2009/06/23 Javascript
复制小说文本时出现的随机乱码的去除方法
2010/09/07 Javascript
js点击页面其它地方将某个显示的DIV隐藏
2012/07/12 Javascript
js字符串转成JSON
2013/11/07 Javascript
js添加select下默认的option的value和text的方法
2014/10/19 Javascript
javascript中new关键字详解
2015/12/14 Javascript
JavaScript的Backbone.js框架环境搭建及Hellow world示例
2016/05/07 Javascript
基于gulp合并压缩Seajs模块的方式说明
2016/06/14 Javascript
Bootstrap编写一个在当前网页弹出可关闭的对话框 非弹窗
2016/06/30 Javascript
js实现添加删除表格(两种方法)
2017/04/27 Javascript
AngularJS模糊查询功能实现代码(过滤内容下拉菜单排序过滤敏感字符验证判断后添加表格信息)
2017/10/24 Javascript
浅析node应用的timing-attack安全漏洞
2018/02/28 Javascript
vue实现提示保存后退出的方法
2018/03/15 Javascript
Angularjs Ng_repeat中实现复选框选中并显示不同的样式方法
2018/09/12 Javascript
在weex中愉快的使用scss的方法步骤
2020/01/02 Javascript
mpvue实现微信小程序快递单号查询代码
2020/04/03 Javascript
js+html+css实现手动轮播和自动轮播
2020/12/30 Javascript
Vue项目打包部署到apache服务器的方法步骤
2021/02/01 Vue.js
python+django加载静态网页模板解析
2017/12/12 Python
python+unittest+requests实现接口自动化的方法
2018/11/29 Python
Python tkinter实现简单加法计算器代码实例
2020/05/13 Python
Python使用pyexecjs代码案例解析
2020/07/13 Python
协程Python 中实现多任务耗资源最小的方式
2020/10/19 Python
Python爬虫破解登陆哔哩哔哩的方法
2020/11/17 Python
如何向scrapy中的spider传递参数的几种方法
2020/11/18 Python
python中scrapy处理项目数据的实例分析
2020/11/22 Python
奥兰多迪士尼门票折扣:Undercover Tourist
2018/07/09 全球购物
英国创新设计文具、卡片和礼品包装网站:Paperchase
2018/07/14 全球购物
优秀员工表扬信
2014/01/17 职场文书
小学生中国梦演讲稿
2014/04/23 职场文书
入职担保书范文
2014/05/21 职场文书
Jedis操作Redis实现模拟验证码发送功能
2021/09/25 Redis
python工具dtreeviz决策树可视化和模型可解释性
2022/03/03 Python