PyTorch ------AlexNet卷積神經網絡實現mnist手寫體識別

  • 接上一篇LeNet現實mnist手寫識別

  • 使用經典模型AlexNet實現相同的功能

  • 先簡單介紹一下,今天的主角,重燃神經網絡輝煌的的模型AlexNet

AlexNet是2012年ImageNet競賽冠軍獲得者Hinton和他的學生設計的,在那年之後,更多的更深的神經網絡如雨後春筍般出現,比如優秀的vgg,GoogLeNet等。 對於傳統的機器學習分類算法而言,已經是相當出色。

  • 簡單介紹一下 AlexNet模型的結構:
    • 結構如下如:
      -在這裏插入圖片描述借用百度百科的圖片展示.
    • 使用的新技術如下:
      • 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)
      訓練結果如下:
      在這裏插入圖片描述
  • 如有什麼地方有問題,或者疑問均可留言討論
  • 真理越辯越明.請賜教
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章