-
接上一篇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(2565*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)
訓練結果如下:
- 結構如下如:
- 如有什麼地方有問題,或者疑問均可留言討論
- 真理越辯越明.請賜教