PyTorch ------AlexNet卷积神经网络实现mnist手写体识别

  • 接上一篇LeNet现实mnist手写识别

  • 使用经典模型AlexNet实现相同的功能

  • 先简单介绍一下,今天的主角,重燃神经网络辉煌的的模型AlexNet

AlexNet是2012年ImageNet竞赛冠军获得者Hinton和他的学生设计的,在那年之后,更多的更深的神经网络如雨后春笋般出现,比如优秀的vgg,GoogLeNet等。 对于传统的机器学习分类算法而言,已经是相当出色。

  • 简单介绍一下 AlexNet模型的结构:
    • 结构如下如:
      -PyTorch ------AlexNet卷积神经网络实现mnist手写体识别_第1张图片借用百度百科的图片展示.
    • 使用的新技术如下:
      • 8层变换,其中有5层卷积和2层全连接隐藏层,以及1个全连接输出层。
      • 将sigmoid激活函数改成了更加简单的ReLU激活函数。
      • 用Dropout来控制全连接层的模型复杂度。
      • 使用CUDA加速深度卷积网络的训练
      • 引入数据增强,如翻转、裁剪和颜色变化,从而进一步扩大数据集来缓解过拟合
    • 代码兼容GPU
    • 这个模型比较复杂,在CPU上很是费劲,尽可能在GPU上运行.
    • 代码中包含可训练参数的计算、features Map的大小计算
    • 代码中备注又不清楚的请留言,我们要做一个严谨的Coder
    • 不能运行的都是耍流氓
    • 下面上代码:

      #引入使用库
      import time
      import torch
      from torch import nn,optim
      import torchvision
      import numpy as np
      import sys
      import os
      import torch.nn.functional as F
      device = torch.device(“cuda” if torch.cuda.is_available() else “cpu”)
      print(device)
      #堆叠 模型
      class AlexNet(nn.Module):
      def init(self):
      super(AlexNet,self).init()
      #堆叠 卷积层 即 特征提取层
      self.conv = nn.Sequential(
      # 输入channel 输出 channel kernel_Size, stride
      # 可训练参数 个数 1111961
      # features map (input_shape Size - 11) / 4 + 1
      # 不能整除 向下取整
      nn.Conv2d(1,96,11,4),
      # 激活函数
      nn.ReLU(),
      # 无可训练参数
      # features map (input_shape Size - kernel_size) / stride + 1
      # 向上取整
      nn.MaxPool2d(3,2),
      nn.Conv2d(96,256,5,1,2),
      nn.ReLU(),
      nn.MaxPool2d(3,2),
      nn.Conv2d(256,384,3,1,1),
      nn.ReLU(),
      nn.Conv2d(384,384,3,1,1),
      nn.ReLU(),
      nn.Conv2d(384,256,3,1,1),
      nn.ReLU(),
      nn.MaxPool2d(3,2)
      )
      #全连接层
      self.fc = nn.Sequential(
      nn.Linear(256
      5*5,4096),
      nn.ReLU(),
      nn.Dropout(0.5),
      # 使用GPU可以使用盖层
      # nn.Linear(4096,4096),
      # nn.ReLU(),
      # nn.Dropout(0.5),
      # 输出层。由于这里使用Fashion-MNIST,所以用类别数为10,而非论文中的1000
      nn.Linear(4096,10)
      )
      def forward(self,imag):
      features = self.conv(imag)
      output = self.fc(features.view(imag.shape[0],-1))
      return output
      net = AlexNet()
      #打印模型结构
      print(net)
      #下载数据 组装好训练数据 测试数据
      def load_data_fashion_mnist(batch_size,resize = None,root = “./dataset/input/FashionMNIST2065”):
      trans = []
      if resize:
      #做数据增强 处理 将图片转化为 规定大小 数据内容不会丢失 等比例 处理
      trans.append(torchvision.transforms.Resize(size=resize))
      #将图片类型转化为Tensor类型
      trans.append(torchvision.transforms.ToTensor())
      #将图片 增强方式 添加到Compose 类中处理
      transform = torchvision.transforms.Compose(trans)
      #读取训练数据
      mnist_train = torchvision.datasets.FashionMNIST(root=root,train=True,download=False,transform = transform)
      #读取 测试数据
      mnist_test = torchvision.datasets.FashionMNIST(root = root,train=False,download=False,transform = transform)
      #数据加载器 在训练 测试阶段 使用多线程按批采样数据 默认不使用多线程 num_worker 表示设置的线程数量
      train_iter = torch.utils.data.DataLoader(mnist_train,batch_size = batch_size,shuffle = True,num_workers = 2)
      test_iter = torch.utils.data.DataLoader(mnist_test,batch_size = batch_size,shuffle = False,num_workers = 2)
      return train_iter,test_iter
      #计算准确率
      def evaluate_accuracy(data_iter,net,device = torch.device(“cpu”)):
      #创建 正确率 和 总个数
      acc_sum ,n = torch.tensor([0],dtype=torch.float32,device=device),0
      for X,y in data_iter:
      #适配 设备
      X,y = X.to(device),y.to(device)
      #设置 验证模式
      net.eval()
      with torch.no_grad(): #隔离开 不要计算在计算图内
      y = y.long()#在这里将y转成long确实是不必要的。但是在计算交叉熵时,Pytorch强制要求y是long
      #累计预测正确的个数
      acc_sum += torch.sum((torch.argmax(net(X),dim=1) == y))
      n += y.shape[0] # 累计总的标签个数
      return acc_sum.item() / n
      #训练函数
      def train_fit(net,train_iter,test_iter,batch_size,optimizer,device,num_epochs):
      #将读取的数据 拷贝到 指定的GPU上
      net = net.to(device)
      print("tainning on ",device)
      #设置 损失函数 交叉熵损失函数
      loss = torch.nn.CrossEntropyLoss()
      #设置训练次数
      for epoch in range(num_epochs):
      train_l_sum,train_acc_sum,n,batch_count,start = 0.0,0.0,0,0,time.time()
      #读取批量数据 进行训练
      for X,y in train_iter:
      X = X.to(device)
      y = y.to(device)
      #训练结果
      y_hat = net(X)
      #计算 预测与标签分布 差异
      l = loss(y_hat,y)
      #优化函数 梯度置为零
      #1、因为梯度可以累加
      #2、每批采样的梯度不同,只需记录本次样本的梯度
      optimizer.zero_grad()
      #反向求导
      l.backward()
      #更新权重参数
      optimizer.step()
      train_l_sum += l.cpu().item()
      #train_acc_sum += (torch.argmax(y_hat,dim = 1) == y).cpu().item()
      #将张量元素值累计
      train_acc_sum += (y_hat.argmax(dim=1) == y).sum().cpu().item()
      n += y.shape[0]
      batch_count += 1
      test_acc = evaluate_accuracy(test_iter,net)
      print(‘epoch %d, loss %.4f, train acc %.3f, test acc %.3f, time %.1f sec’
      % (epoch + 1, train_l_sum / batch_count, train_acc_sum / n, test_acc, time.time() - start))
      lr,num_epochs = 0.001,10
      #优化器 设置为 Adam
      optimizer = torch.optim.Adam(net.parameters(),lr = lr)
      train_fit(net,train_iter,test_iter,batch_size,optimizer,device,num_epochs)
      训练结果如下:
      PyTorch ------AlexNet卷积神经网络实现mnist手写体识别_第2张图片
  • 如有什么地方有问题,或者疑问均可留言讨论
  • 真理越辩越明.请赐教

你可能感兴趣的:(CNN)