日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

基于PyTorch框架的多层全连接神经网络实现MNIST手写数字分类

發布時間:2024/10/8 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于PyTorch框架的多层全连接神经网络实现MNIST手写数字分类 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

多層全連接神經網絡實現MNIST手寫數字分類

  • 1 簡單的三層全連接神經網絡
  • 2 添加激活函數
  • 3 添加批標準化
  • 4 訓練網絡
  • 5 結論
  • 參考資料

先用PyTorch實現最簡單的三層全連接神經網絡,然后添加激活層查看實驗結果,最后再加上批標準化驗證是否能夠更加有效。

1 簡單的三層全連接神經網絡

  • 對于這個三層網絡,需要傳遞進去的參數包括:輸入的維度,第一次網絡的神經元個數,第二層網絡神經元的個數,以及第三層網絡(輸出層)神經元個數。
import torch import torch.nn as nn from torch.autograd.variable import Variable import numpy as np# 定義三層全連接神經網絡 class SimpleNet(nn.Module):def __init__(self, in_dim, n_hidden_1, n_hidden_2, out_dim):super(SimpleNet, self).__init__()self.layer1 = nn.Linear(in_dim, n_hidden_1)self.layer2 = nn.Linear(n_hidden_1, n_hidden_2)self.layer3 = nn.Linear(n_hidden_2, out_dim)def forward(self, x):x = self.layer1(x)x = self.layer2(x)x = self.layer3(x)return x

2 添加激活函數

  • 接著改進一下網絡,添加激活函數增加網絡的非線性
# 添加激活函數,增加網絡的非線性 class Activation_Net(nn.Module):def __init__(self, in_dim, n_hidden_1, n_hidden_2, out_dim):super(Activation_Net, self).__init__()self.layer1 = nn.Sequential(nn.Linear(in_dim, n_hidden_1), nn.ReLU(True))self.layer2 = nn.Sequential(nn.Linear(n_hidden_1, n_hidden_2))self.layer3 = nn.Sequential(nn.Linear(n_hidden_2, out_dim))def forward(self, x):x = self.layer1(x)x = self.layer2(x)x = self.layer3(x)return x
  • 這里只需要在每層網絡的輸出部分添加激活函數就可以了,nn.Sequential()這個函數是將網絡的層組合到一起,比如上面將nn.Linear()和nn.ReLU()組合到一起作為self.layer。最后一層輸出層不能添加激活函數,因為輸出的結果表示的是實際的得分。

3 添加批標準化

  • 最后添加一個加快收斂速度的方法–批標準化。
class Batch_Net(nn.Module):def __init__(self, in_dim, n_hidden_1, n_hidden_2, out_dim):super(Batch_Net, self).__init__()self.layer1 = nn.Sequential(nn.Linear(in_dim, n_hidden_1),nn.BatchNorm1d(n_hidden_1),nn.ReLU(True))self.layer2 = nn.Sequential(nn.Linear(n_hidden_1, n_hidden_2),nn.BatchNorm1d(n_hidden_2),nn.ReLU(True))self.layer3 = nn.Sequential(nn.Linear(n_hidden_2, out_dim))def forward(self, x):x = self.layer1(x)x = self.layer2(x)x = self.layer3(x)return x
  • 同樣使用nn.Sequential()將nn.BatchNorm1d()組合到網絡層中,注意批標準化一般放在全連接層的后面,非線性層(激活函數)的前面。

4 訓練網絡

  • 網絡的定義較簡單,現在用MNIST數據集訓練網絡并測試一下每種網絡的結果。
  • MNIST數據集是一個手寫字體數據集,包括0~9這10個數字,其中有55000張訓練集,10000張測試集,5000張驗證集,圖片是28*28的灰度圖。
  • 導入需要用的包
import torch from torch import nn, optim from torch.autograd import Variable from torch.utils.data import DataLoader from torchvision import datasets, transforms import net
  • 定義超參數
# 超參數 Hyper parameters batch_size = 64 learning_rate = 1e-2 num_epochs = 20
  • 數據預處理,需要將數據標準化,運用的函數是torchvision.transforms,它提供了很多圖片預處理的方法。transforms.ToTensor()將圖片轉換成PyTorch中處理的對象Tensor,在轉換的過程中,PyTorch自動將圖片標準化,即Tensor的范圍是0~1。transforms.Normalize()需要傳入兩個參數,第一個是均值,第二個是方差,做的處理就是減均值,再除以方差。

  • transforms.Compose()將各種預處理操作組合到一起,transforms.Normalize([0.5], [0.5])表示減去0.5再除以0.5,這樣圖片轉換到-1到1之間。因為圖片是灰度圖片,所以只有一個通道,如果是彩色圖像,有三個通道,用transforms.Normalize([mean_r,mean_g,mean_b], [var_r,var_g,var_b])來表示每個通道對應的均值和方差。

# 數據預處理 data_tf = transforms.Compose([# 將圖片轉換成PyTorch中處理的對象Tensor,在轉換的過程中自動將圖片標準化,即Tensor的范圍是0~1transforms.ToTensor(),# 第一個參數是均值,第二個參數是方差,做的處理就是減均值,再除以方差transforms.Normalize([0.5], [0.5])] )
  • 讀取數據集。
  • 通過PyTorch的內置函數torchvision.datasets.MNIST導入數據集,傳入數據預處理。使用torch.utils.data.DataLoader建立一個數據迭代器,傳入數據集和batch_size,通過shuffle=True,來表示每次迭代數據的時候是否將數據打亂。
# 下載訓練集MNIST手寫數字訓練集 train_dataset = datasets.MNIST(root='./data',train=True,transform=data_tf,download=True ) test_dataset = datasets.MNIST(root='./data',train=False,transform=data_tf ) train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True) test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)
  • 導入網絡,定義損失函數和優化方法。
  • 通過net.SimpleNet定義簡單三層網絡,里面的參數是2828,300,100,10,其中輸入的維度是2828,因為輸入圖片大小是28*28,然后定義兩個隱藏層分別是300和100。最后輸出的結果必須是10,因為這是一個分類問題,一共有0~9這10個數字,所以是10分類。
  • 損失函數定義為分類問題中最常見的損失函數交叉熵,使用隨機梯度下降來優化損失函數。
# 導入網絡 model = net.SimpleNet(28 * 28, 300, 100, 10) if torch.cuda.is_available():model = model.cuda()# 定義損失函數和優化方法 criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(model.parameters(), lr=learning_rate)
  • 開始訓練網絡
  • img = Variable(img, volatile=True)里面的volatile=True表示前向傳播時,不會保留緩存,因為對于測試集,不需要做反向傳播,所以在前向傳播時釋放內存,節約內存空間。
# 開始訓練網絡 model.eval() eval_loss = 0 eval_acc = 0 for data in test_loader:img, label = dataimg = img.view(img.size(0), -1)if torch.cuda.is_available():img = Variable(img, volatile=True).cuda()label = Variable(label, volatile=True).cuda()else:img = Variable(img, volatile=True)label = Variable(label, volatile=True)out = model(img)loss = criterion(out, label)eval_loss += loss.data[0] * label.size(0)_, pred = torch.max(out, 1)num_correct = (pred == label).sum()eval_acc += num_correct.data[0] print('Test Loss:{:.6f},ACC:{:.6f}'.format(eval_loss / (len(test_dataset)),eval_acc / (len(test_dataset))) )

5 結論

  • 依次測試簡單三層網絡、添加激活層的網絡、添加批標準化的網絡,網絡的預測準確率越來越高,同時還可以通過Dropout、正則化,增加網絡的泛化能力。
import torch import torch.nn from torchvision import datasets from torchvision import transforms from torch.utils.data import DataLoader import torch.nn.functional as Fdevice = torch.device('cuda:0'if torch.cuda.is_available()else 'cpu') batch_size = 32 transform = transforms.Compose([transforms.ToTensor() ]) train_set = datasets.MNIST(root='./dataset/mnist',train=True,transform=transform) train_loader = DataLoader(dataset=train_set,batch_size=batch_size,shuffle=True,num_workers=2) test_set = datasets.MNIST(root='./dataset/mnist',train=False,transform=transform) test_loader = DataLoader(dataset=test_set,batch_size=batch_size,shuffle=False,num_workers=2)class Net(torch.nn.Module):def __init__(self):super(Net, self).__init__()self.conv1 = torch.nn.Conv2d(in_channels=1, out_channels=10, kernel_size=5)self.conv2 = torch.nn.Conv2d(in_channels=10, out_channels=20, kernel_size=5)self.pooling = torch.nn.MaxPool2d(kernel_size=2)self.fc = torch.nn.Linear(320, 10)def forward(self, x):# Flatten data from (n,1,28,28) to (n,784)batch_size = x.size(0)x = F.relu(self.pooling(self.conv1(x)))x = F.relu(self.pooling(self.conv2(x)))x = x.view(batch_size, -1) # Flattenx = self.fc(x)return xmodel = Net().to(device) criterion = torch.nn.CrossEntropyLoss() optimizer = torch.optim.SGD(params=model.parameters(),lr=0.01, momentum=0.5)def train(epoch):running_loss = 0for batch_idx, data in enumerate(train_loader):images, labels = dataimages = images.to(device)labels = labels.to(device)optimizer.zero_grad()outputs = model(images)loss = criterion(outputs, labels)loss.backward()optimizer.step()running_loss += loss.item()if (batch_idx + 1) % 300 == 0:print('[%d,%d],loss is %.2f' %(epoch, batch_idx, running_loss / 300))running_loss = 0def test():correct = 0total = 0with torch.no_grad():for data in test_loader:images, labels = dataimages = images.to(device)labels = labels.to(device)outputs = model(images)_, predict = torch.max(outputs, dim=1)correct += (labels == predict).sum().item()total += labels.size(0)print('correct/total:%d/%d,Accuracy:%.2f%%' % (correct, total, 100 * (correct / total)))if __name__ == '__main__':for epoch in range(10):train(epoch)test()

參考資料

  • 廖星宇《深度學習入門之PyTorch》電子工業出版社
  • 與50位技術專家面對面20年技術見證,附贈技術全景圖

    總結

    以上是生活随笔為你收集整理的基于PyTorch框架的多层全连接神经网络实现MNIST手写数字分类的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。