基於PyTorch的深度學習快速入門教程

最近小組彙報正好用到了pytorch,因此想把相關內容整理成博客(彙報ppt和演示代碼附在最後了,有須要的話能夠自取)。主要參考了《Python深度學習:基於PyTorch》的前幾章和網上的一些入門教程,側重代碼。經過這篇博客 ,你能夠:html

  1. 對PyTorch框架有初步的瞭解python

  2. 對PyTorch中的Tensor張量、autograd自動求導、反向傳播等概念有必定了解並掌握相關代碼git

  3. 用PyTorch實現一個簡單的機器學習算法(函數擬合)github

  4. 使用PyTorch神經網絡工具箱搭建一個簡單的卷積神經網絡模型(minist手寫數字識別)算法

  5. 訓練搭建的網絡並經過該模型來進行預測

    數組


1、PyTorch簡介

1.1 PyTorch簡介

PyTorch源於深度學習框架Torch,Torch使用了一種不是很大衆的語言Lua做爲接口,用的人不是不少,因此開發團隊在Torch的基礎上使用Python重寫的一個全新的深度學習框架,也就是PyTorch。
雖然PyTorch的前身是Torch,但其與Torch 的不一樣之處在於PyTorch 不只更加靈活,支持動態圖,並且提供了Python接口。PyTorch 既能夠看作加入了GPU 支持的numpy,同時也能夠當作一個擁有自動求導功能的強大的深度神經網絡。它更像NumPy的替代產物,不只繼承了NumPy的衆多優勢,還支持GPU計算,在計算效率上要比NumPy有更明顯的優點;不只如此,PyTorch還有許多高級功能,好比擁有豐富的API,能夠快速完成深度神經網絡模型的搭建和訓練。因此PyTorch一經發布,便受到了衆多開發人員和科研人員的追捧和喜好,成爲 AI從業者的重要工具之一。
網絡

1.2 PyTorch優勢

  • 簡潔
    PyTorch追求最少的封裝,儘可能避免重複造輪子,不像TensorFlow中充斥着session、graph、operation、name_scope、variable、tensor、layer等全新的概念
    PyTorch的設計遵循表明高維數組( tensor )、自動求導( variable\autograd)和神經網絡( nn.Module )三個由低到高的抽象層次,並且這三個抽象之間聯繫緊密,能夠同時進行修改和操做,其中nn.Module則是PyTorch中對全部模型對象的封裝

  • 易用
    如今的深度學習平臺在定義模型的時候主要用兩種方式:static computation graph(靜態圖模型) 和 dynamic computation graph(動態圖模型)。 絕大部分平臺都採用的是static的定義方式,包括TensorFlow, Theano, Caffe,Keras等
    靜態圖須要在處理數據前定義好一套完整的模型;而動態圖模型容許用戶先定義好一套基本的框架再根據數據來實時修正模型
    靜態圖定義的缺陷是在處理數據前必須定義好完整的一套模型,可以處理全部的邊際狀況,好比在聲明模型前必須知道整個數據中句子的最大長度。相反動態圖模型(現有的平臺好比PyTorch, Chainer, Dynet)可以很是自由的定義模型
    PyTorch不只定義網絡結構簡單,並且還很直觀靈活。它支持autograd,因此不用本身去定義和數學推導back-propagation,還支持動態圖模型,能夠無縫銜接numpy



  • 速度快
    PyTorch的靈活性不以速度爲代價,在許多評測中,PyTorch的速度表現賽過TensorFlow和Keras等框架 。一樣的算法,使用PyTorch實現的更有可能快過用其餘框架實現的
  • 社區活躍
    PyTorch提供了完整的文檔,有facebook的FAIR強力支持(FAIR是全球TOP3的AI研究機構),開源方案也不少

1.3 PyTorch的安裝

主要流程:session

  1. 在anaconda中建立python環境,並將路徑添加到系統環境變量中
  2. 在pytorch官網複製安裝命令https://pytorch.org/get-started/locally/
  3. 在命令行中安裝pytorch
  4. Import torch測試安裝是否成功

具體能夠參考博客http://www.javashuo.com/article/p-sfixeogi-ne.html框架

2、PyTorch基礎

2.1 Numpy

NumPy是 Python 語言的一個擴展程序庫,支持大量的維度數組與矩陣運算,此外也針對數組運算提供大量的數學函數庫,在機器學習和深度學習中常常用到。dom

2.1.1 numpy數組的定義

  • 直接定義
import numpy as np
x1 = np.array([1.0, 2.0, 3.0])
X2=np.array((1.0, 2.0, 3.0))
  • 將列表list轉換爲numpy數組
b=[2.0,4.0,6.0]
y=np.array(a)
  • 將numpy數組轉換爲列表list
z= np.array([1.0, 2.0, 3.0]) 
c=list(z)

2.1.2 numpy數組的元素訪問

對於矩陣A=np.array([1,2,3],[4,5,6])

  • A[i]得到矩陣A的第i行
  • A[i][j]得到元素Aij
  • A[i][j:k]得到數組A[i]的j到k-1元素

2.1.3 numpy數組的計算

  • 加法:x+y
  • 乘法:x*y
  • 廣播:x*10=[1.0, 2.0, 3.0]10=[1.0, 2.0, 3.0] [10, 10, 10]

2.2 Tensors張量

2.2.1 Tensors

2.2.2 Tensors的使用

  1. 導入包
import torch
  1. 構建一個5*3的矩陣
x = torch.Tensor(5, 3)  # 未初始化
y = torch.rand(5, 3)  # 隨機初始化
  1. 將torch的Tensor轉換爲numpy的array
a=x.numpy() # Tensor轉array
x=torch.from_numpy(a)  # array轉Tensor
  1. 運算:
  • 加減法:y.add_(x)、z=x+y、torch.add(x,y,out=z)、z=torch.sub(x,y)
  • 乘法: x*y、torch.mul(x,y)
  • 裁剪:y=torch.clamp(x,-0.1,0.1)
    更多運算可參考官方說明文檔
  1. CUDA Tensors:
    使用 .cuda 函數將Tensors移動到GPU
if torch.cuda.is_available():
    x = x.cuda()
    y = y.cuda()

2.3 autograd自動求導

2.3.1 Variable變量
將Tensor轉換爲Variable以後,能夠裝載梯度信息,一旦前向計算,能夠經過.backward()方法來自動計算全部的梯度

2.3.2 gradient descent梯度降低
損失函數關於模型參數的梯度指向一個能夠下降損失函數值的方向,能夠不斷地沿着梯度的方向更新模型從而最小化損失函數

2.3.3 Autograd自動求導
對於複雜的模型,例如多達數十層的神經網絡,手動計算梯度很是困難,所以PyTorch提供了Autograd包來自動化求導過程,它會有一個記錄咱們全部執行操做的記錄器,以後再回放記錄來計算梯度
這一技術在構建神經網絡時尤爲有效,由於咱們能夠經過計算前路參數的微分來節省時間

2.4 利用Numpy實現函數擬合

import numpy as np
from matplotlib import pyplot as plt
# 生成 輸入數據x 及 目標數據y
np.random.seed(100)
x = np.linspace(-1,1,100).reshape(100,1)
y = 3*np.power(x,2)+2+0.2*np.random.rand(x.size).reshape(100,1)
# 查看x、y數據分佈狀況
plt.scatter(x,y)
plt.show()
# 初始化權重參數
w1 = np.random.rand(1,1)
b1 = np.random.rand(1,1)
# 訓練模型
lr = 0.001 # 學習率
for i in range(800): #梯度降低
    y_pred = np.power(x,2)*w1+b1

    loss = 0.5*(y_pred - y)**2  # 損失函數
    loss = loss.sum()  # 方差
    # 梯度降低法
    grad_w = np.sum((y_pred - y)*np.power(x,2))
    grad_b = np.sum((y_pred - y))
    w1 -= lr*grad_w  # 將學習率看做步長
    b1 -= lr*grad_b
# 可視化結果
plt.plot(x,y_pred,'r-',label='predict')
plt.scatter(x,y,color='blue',marker='o',label='true') # true data
plt.xlim(-1,1)
plt.ylim(2,6)
plt.legend()
plt.show()
print(w1,b1)

目標函數設爲y_pred=w1 * x^2+b1,求解目標函數至關於求解參數w1和b1
這裏定義的loss函數爲0.5*(y_pred - y)^2之和,至關於方差(按照吳恩達視頻,乘以0.5能夠方便求導時把次方2係數消掉,因此實際乘以了0.5),loss函數值越小,偏差也就越小,因此至關於求解使得loss值最小的w1和b1,這樣的目標函數和實際函數是最接近的。
grad_w是w1的梯度,至關於loss對w1的偏導,grad_b是b1的梯度,至關於loss對b1的偏導,沿着梯度方向能夠最快到達loss最低點。
注意,這裏的梯度是咱們本身手動計算獲得的,大概這麼個過程:
在這裏插入圖片描述
所以




grad_w = np.sum((y_pred - y)*np.power(x,2))
    grad_b = np.sum((y_pred - y))

而後讓w1和b1每次沿着梯度方向挪動一小步,這樣w1和w2的梯度會愈來愈小,當接近0的時候也就獲得了loss可能的極小值點

w1 -= lr*grad_w  # 將學習率看做步長
    b1 -= lr*grad_b

將計算過程循環800次,輸出不斷更新後的w1和b1,並輸出擬合圖像
運行結果:
原始數據
在這裏插入圖片描述
在這裏插入圖片描述
能夠得出w1=2.98927619,b1=2.09818307,目標函數y_pred=2.98927619x^2+2.09818307。




2.5 利用PyTorch實現函數擬合

咱們能夠看到,當函數比較簡單時,梯度用手動計算也很方便,可是當函數比較複雜時,計算便會十分艱鉅,而pythorch的自動求導就完美解決了這一問題,只需給出正向計算過程,pytorch會自動爲你反向計算梯度,接下來仍是以上一狀況爲例,可是使用PyTorch來實現。

import numpy as np
import torch
from matplotlib import pyplot as plt
# 生成 輸入數據x 及 目標數據y
np.random.seed(100)
x = np.linspace(-1,1,100).reshape(100,1)
y = 3*np.power(x,2)+2+0.2*np.random.rand(x.size).reshape(100,1)
x=torch.tensor(x)
y=torch.tensor(y)
# 查看x、y數據分佈狀況
plt.scatter(x,y)
plt.show()
# 初始化權重參數
w1 =torch.zeros(1,1,requires_grad=True)
b1 =torch.zeros(1,1,requires_grad=True)
# 訓練模型
lr = 0.001 # 學習率
cost = []
for i in range(800): #梯度降低
    y_pred = w1*x**2 + b1
    loss = torch.sum((y_pred - y) ** 2)
    loss.backward()
    # 參數更新
    print(w1.grad.data.item(),b1.grad.data.item())
    # 梯度降低法
    w1.data = w1.data - lr*w1.grad.data  # 將學習率看做步長
    b1.data = b1.data - lr*b1.grad.data
    w1.grad.data.zero_()  #梯度清零
    b1.grad.data.zero_()

# 可視化結果
plt.plot(x,y_pred.data,'r-',label='predict')
plt.scatter(x,y,color='blue',marker='o',label='true') # true data
plt.xlim(-1,1)
plt.ylim(2,6)
plt.legend()
plt.show()
print(w1.data,b1.data)

數據和處理過程和前面都差很少,主要來看自動求導這塊。首先在定義w1和w2的時候,w1 =torch.zeros(1,1,requires_grad=True),意思是初試化1行1列的tensor w1初值爲0,requires_grad默認值爲false,賦值爲True表示以後須要求解梯度

w1 =torch.zeros(1,1,requires_grad=True)
b1 =torch.zeros(1,1,requires_grad=True)

而後給出原始函數y_pred=w1 * x^2+b1,loss=Σ0.5*(y_pred - y)^2以後直接loss.backward(),表示從loss反向傳播,計算loss到w1和b1的偏導,機器的具體計算過程能夠參考計算圖與自動求導,這樣就不用手動計算對應的梯度公式,直接w1.grad.data.item()得到梯度的數值(w1.grad就能夠得到梯度,可是獲得的結果是一個tensor變量)
注意,每次循環都須要對梯度進行清零,不然每輪次梯度會累加前面的梯度,越算越大,與梯度降低的目的相悖

w1.grad.data.zero_()  #梯度清零

3、PyTorch神經網絡工具箱

3.1 卷積神經網絡層次

卷積神經網絡是一種包含卷積計算操做且具備深度層次結構的前饋型神經網絡,與傳統神經網絡的區別在於卷積神經網絡的層和形式有了很大的變化,能夠說是傳統神經網絡的一個改進。以下圖所示,傳統神經網絡主要包括一個輸入層、一個輸出層,還有若干中間層,而卷積神經網絡有許多傳統神經網絡沒有的層次。

傳統神經網絡結構
卷積神經網絡結構
在這裏插入圖片描述
輸入層也就是你喂進去的大量訓練數據,因此主要介紹pytorch對其餘幾個層級的實現:


3.1.1 卷積層

卷積計算層是卷積神經網絡的核心層次,由若干卷積單元組成。在這個卷積層裏,主要包含兩個關鍵操做,一個關鍵操做是局部關聯,它將每一個神經元看作一個濾波器(filter),另外一個關鍵操做是窗口(receptive
field)滑動,讓filter對局部數據計算。卷積計算層由若干卷積單元組成,每一個卷積單元是一個權值矩陣,它會在二維的輸入數據上每次滑動固定步長,而後將對應的窗口的元素值進行矩陣的乘法,把獲得的計算結果輸出到像素。
如圖8就是一次卷積計算操做,其中左邊的矩陣是初始輸入的原始矩陣,中間矩陣爲卷積核(filter),右側是通過卷積計算後獲得的輸出值。經過卷積運算能夠提取輸入的不一樣特徵,並且逐層增強,好比第一層卷積計算層可能只能提取低級特徵,而更高層的網路能夠從低級特徵中迭代提取更爲複雜的特徵。

在這裏插入圖片描述
pytoch實現:

一維卷積: 多用於處理文本,只計寬度不計高度

conv1 = nn.Conv1d(in_channels=256, out_channels=100,
kernel_size=2)
input = torch.randn(32, 35, 256)
input = input.permute(0, 2, 1)
output = conv1(input)

二維卷積: 多用於處理圖像

from PIL import Image
from torchvision.transforms
import ToTensor, ToPILImage
to_tensor = ToTensor()  # img ->tensor
to_pil = ToPILImage()  # tensor -> image
ll =Image.open('imgs/lena.png')  
input =to_tensor(lena).unsqueeze(0)

3.1.2 激活層

在神經網絡中加入激活函數的話能夠引入非線性因素,還能提升本模型的表達強度,縮小模型的訓練時間,使訓練成本降低,解決不少線性模型不能解決的問題。

pytoch實現 relu函數:
relu函數

relu = nn.ReLU(inplace=True)
output = relu(input)
# output = input.clamp(min=0)

3.1.3 池化層

池化層(Pooling layer)本質上是採樣操做,而上採樣(upsampling)是將feature map還原,與上採樣不一樣的是池化爲下采樣(subsampling)操做,一是壓縮數據量,即壓縮輸入的特徵圖像來縮小圖像尺寸來達到減少所需顯存的目的;二是將feature map變小,即壓縮輸入的圖像特徵中的特徵值減少計算量,去除特徵值中重複冗餘的信息以保留最主要的特徵,改善過擬合的狀況。

常見的池化操做包括平均池化(average
pooling)和最大池化(max pooling),其中平均池化是將圖像區域的平均值看成該區域池化後的取值,平均池化能很好的保留背景可是會使圖片變得模糊,而最大池化則是選取圖像區域的最大值看成該區域池化後的取值,能比較好的保留圖片紋理特徵,通常來講最大池化比平均池化要更爲經常使用。

平均池化:
平均池化
最大池化:
最大池化
pytoch實現:



pool1= nn.AvgPool2d(2,2)  # 平均池化
pool2= nn. MaxPool2d(2,2)  # 最大池化
out   = pool1( V(input) )
out   = pool2( V(input) )

3.1.4 全鏈接層(輸出層)

在卷積神經網絡中,通過多個卷積層和池化層後卷積神經網絡的尾部通常會存在1個及以上的全鏈接層,主要負責與上一層的全部神經元進行全鏈接,整合卷積層和池化層中取得的局部特徵以獲得最終的特徵圖像。

pytoch實現:

input = V(t.randn(2,3))
linear = nn.Linear(3,4)
h = linear(input)

3.2 PyTorch搭建卷積神經網絡——MNIST手寫數字識別

接下來以mnist手寫數字識別爲例使用PyTorch神經網絡工具箱搭建一個簡單的卷積神經網絡模型(完整代碼在最後)

首先獲取訓練數據集

# 獲取訓練集dataset
training_data = torchvision.datasets.MNIST(
    root='./data/',  # dataset存儲路徑
    train=True,  # True表示是train訓練集,False表示test測試集 
    transform=torchvision.transforms.ToTensor(),  # 將原數據規範化到(0,1)區間
    download=DOWNLOAD_MNIST,
)

# 打印MNIST數據集的訓練集及測試集的尺寸
print(training_data.data.size())   # torch.Size([60000, 28, 28])
print(training_data.targets.size())   # torch.Size([60000])
# 打印一張看看長啥樣
plt.imshow(training_data.data[0].numpy(), cmap='gray')
plt.title('simple')
plt.show()

#經過torchvision.datasets獲取的dataset格式可直接可置於DataLoader
train_loader = Data.DataLoader(dataset=training_data,
batch_size=BATCH_SIZE,shuffle=True)

# 獲取測試集dataset
test_data = torchvision.datasets.MNIST(root='./data/',train=False)

# 取前2000個測試集樣本
test_x = Variable(torch.unsqueeze(test_data.data, dim=1),volatile=True).type(torch.FloatTensor)[:2000] / 255
# (2000, 28, 28) to (2000, 1, 28, 28), in range(0,1)
test_y = test_data.targets[:2000]

這是pytorch自帶的數據集,圖片長這樣在這裏插入圖片描述
若是你沒有mnist數據集的話它會給你自動下載,可是下載會很慢,因此能夠自行下載以後新建data目錄,而後把下載好的數據集放進去,節約時間

連接:https://pan.baidu.com/s/1TlvwqzkvfICdAceHITcMyw
提取碼:u0nk

在這裏插入圖片描述
在這裏插入圖片描述
能夠看到MNIST目錄下有processed和raw兩個目錄,processed是用來放訓練過程當中產生的訓練文件,不太用管,而raw目錄纔是存放訓練圖片的
在這裏插入圖片描述


而後設計cnn網絡結構,定義一個具備以下結構的卷積神經網絡
在這裏插入圖片描述

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Sequential(  # (1,28,28)
            nn.Conv2d(in_channels=1, out_channels=16, kernel_size=5,
                      stride=1, padding=2),  # (16,28,28)
            # 想要con2d卷積出來的圖片尺寸沒有變化, padding=(kernel_size-1)/2
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2)  # (16,14,14)
        )
        self.conv2 = nn.Sequential(  # (16,14,14)
            nn.Conv2d(16, 32, 5, 1, 2),  # (32,14,14)
            nn.ReLU(),
            nn.MaxPool2d(2)  # (32,7,7)
        )
        self.out = nn.Linear(32 * 7 * 7, 10)

    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = x.view(x.size(0), -1)  # 將(batch,32,7,7)展平爲(batch,32*7*7)
        output = self.out(x)
        return output

拆開細看,定義的cnn總體結構:

CNN(
(conv1): Sequential(
(0): Conv2d(1, 16, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
(1): ReLU()
(2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(conv2): Sequential(
(0): Conv2d(16, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
(1): ReLU()
(2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(out): Linear(in_features=1568, out_features=10, bias=True)
)











其中一共有兩大塊——conv一、conv2

conv1包含一個二維卷積層:

nn.Conv2d(in_channels=1, out_channels=16, kernel_size=5,
                      stride=1, padding=2),  # (16,28,28)

一個激勵層:

nn.ReLU()

一個平均池化層:

nn.MaxPool2d(kernel_size=2)

而conv2同理。
最後是一個全鏈接層,也能夠說是輸出層

self.out = nn.Linear(32 * 7 * 7, 10)

而forward是原始的計算過程,以後能夠用來反向傳播

def forward(self, x):
    x = self.conv1(x)
    x = self.conv2(x)
    x = x.view(x.size(0), -1)  # 將(batch,32,7,7)展平爲(batch,32*7*7)
    output = self.out(x)
    return output

這裏的x至關於輸入層,先把x放入第一塊conv1(卷積——激勵——池化),以後把輸出結構再放入第二塊conv2(卷積——激勵——池化),再放入輸出層out,最後返回輸出結果output

3.3 模型訓練與預測

訓練搭建的網絡並經過該模型來預測

先實例化剛剛設計的cnn網絡cnn = CNN(),而後設置一個Adam優化器進行優化

optimizer = torch.optim.Adam(cnn.parameters(), lr=LR)
loss_function = nn.CrossEntropyLoss()

循環訓練

for epoch in range(EPOCH):
    for step, (x, y) in enumerate(train_loader):
        b_x = Variable(x)
        b_y = Variable(y)

        output = cnn(b_x)
        loss = loss_function(output, b_y)  #損失函數
        optimizer.zero_grad()   
        loss.backward()
        optimizer.step()

        if step % 100 == 0:
            test_output = cnn(test_x)
            pred_y = torch.max(test_output, 1)[1].data.squeeze()
            s1=sum(pred_y == test_y)
            s2=test_y.size(0)
            accuracy = s1/(s2*1.0)
            print('Epoch:', epoch, '|Step:', step,
                  '|train loss:%.4f' % loss.item(), '|test accuracy:%.4f' % accuracy)

其中optimizer.zero_grad()是清除以前的梯度,而後對loss調用backward(),最後,調用optimizer.step()將更新的值加到model的parameters上。
關於optimizer(torch.optim)的使用

每訓練100次就輸出當前的loss值和準確度,其中準確度accuracy = 預測結果和正確結果相同的總數/總數

Epoch: 0 |Step: 0 |train loss:2.3105 |test accuracy:0.0605
Epoch: 0 |Step: 100 |train loss:0.1290 |test accuracy:0.8735
Epoch: 0 |Step: 200 |train loss:0.4058 |test accuracy:0.9285
Epoch: 0 |Step: 300 |train loss:0.1956 |test accuracy:0.9440
Epoch: 0 |Step: 400 |train loss:0.1238 |test accuracy:0.9585
Epoch: 0 |Step: 500 |train loss:0.2217 |test accuracy:0.9630
Epoch: 0 |Step: 600 |train loss:0.0237 |test accuracy:0.9670
Epoch: 0 |Step: 700 |train loss:0.2158 |test accuracy:0.9700
Epoch: 0 |Step: 800 |train loss:0.0433 |test accuracy:0.9720
Epoch: 0 |Step: 900 |train loss:0.0564 |test accuracy:0.9770
Epoch: 0 |Step: 1000 |train loss:0.0320 |test accuracy:0.9760
Epoch: 0 |Step: 1100 |train loss:0.0233 |test accuracy:0.9825










能夠看到梯度在不斷降低,而準確度在不斷增長。

而後拿訓練好的模型進行預測

test_output = cnn(test_x[:10])
pred_y = torch.max(test_output, 1)[1].data.numpy().squeeze()
print(pred_y, 'prediction number')
print(test_y[:10].numpy(), 'real number')

for n in range(10):
    plt.imshow(test_data.data[n].numpy(), cmap='gray')
    plt.title('data[%i' % n+']: test:%i' % test_data.targets[n]+' pred:%i' % pred_y[n])
    plt.show()

在測試集中拿出前10張圖片放入訓練好的網絡中test_output = cnn(test_x[:10])(也能夠裁取別的部分),得到預測值pred_y = torch.max(test_output, 1)[1].data.numpy().squeeze(),而後輸出這10張圖片的預測值和實際標籤

結果:
[7 2 1 0 4 1 4 9 5 9] prediction number
[7 2 1 0 4 1 4 9 5 9] real number

同時還能夠在圖像中展現plt.imshow(test_data.data[n].numpy(), cmap='gray')

部分結果:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述



能夠看到,識別的仍是蠻準確的。


附:手寫數字識別完整代碼:

import torch
import torch.nn as nn
from torch.autograd import Variable
import torch.utils.data as Data
import torchvision
import matplotlib.pyplot as plt

torch.manual_seed(1)

EPOCH = 1
BATCH_SIZE = 50
LR = 0.001
DOWNLOAD_MNIST = True

# 獲取訓練集dataset
training_data = torchvision.datasets.MNIST(
    root='./data/',  # dataset存儲路徑
    train=True,  # True表示是train訓練集,False表示test測試集
    transform=torchvision.transforms.ToTensor(),  # 將原數據規範化到(0,1)區間
    download=DOWNLOAD_MNIST,
)

# 打印MNIST數據集的訓練集及測試集的尺寸
print(training_data.data.size())
print(training_data.targets.size())
# torch.Size([60000, 28, 28])
# torch.Size([60000])
plt.imshow(training_data.data[0].numpy(), cmap='gray')
plt.title('simple')
plt.show()

# 經過torchvision.datasets獲取的dataset格式可直接可置於DataLoader
train_loader = Data.DataLoader(dataset=training_data, batch_size=BATCH_SIZE,
                               shuffle=True)

# 獲取測試集dataset
test_data = torchvision.datasets.MNIST(root='./data/', train=False)
# 取前2000個測試集樣本

test_x = Variable(torch.unsqueeze(test_data.data, dim=1),
                  volatile=True).type(torch.FloatTensor)[:2000] / 255
# (2000, 28, 28) to (2000, 1, 28, 28), in range(0,1)
test_y = test_data.targets[:2000]


class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Sequential(  # (1,28,28)
            nn.Conv2d(in_channels=1, out_channels=16, kernel_size=5,
                      stride=1, padding=2),  # (16,28,28)
            # 想要con2d卷積出來的圖片尺寸沒有變化, padding=(kernel_size-1)/2
            nn.ReLU(),
            nn.MaxPool2d(kernel_size=2)  # (16,14,14)
        )
        self.conv2 = nn.Sequential(  # (16,14,14)
            nn.Conv2d(16, 32, 5, 1, 2),  # (32,14,14)
            nn.ReLU(),
            nn.MaxPool2d(2)  # (32,7,7)
        )
        self.out = nn.Linear(32 * 7 * 7, 10)

    def forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = x.view(x.size(0), -1)  # 將(batch,32,7,7)展平爲(batch,32*7*7)
        output = self.out(x)
        return output


cnn = CNN()
print(cnn)

optimizer = torch.optim.Adam(cnn.parameters(), lr=LR)
loss_function = nn.CrossEntropyLoss()

for epoch in range(EPOCH):
    for step, (x, y) in enumerate(train_loader):
        b_x = Variable(x)
        b_y = Variable(y)

        output = cnn(b_x)
        loss = loss_function(output, b_y)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if step % 100 == 0:
            test_output = cnn(test_x)
            pred_y = torch.max(test_output, 1)[1].data.squeeze()
            s1=sum(pred_y == test_y)
            s2=test_y.size(0)
            accuracy = s1/(s2*1.0)
            print('Epoch:', epoch, '|Step:', step,
                  '|train loss:%.4f' % loss.item(), '|test accuracy:%.4f' % accuracy)

test_output = cnn(test_x[:10])
pred_y = torch.max(test_output, 1)[1].data.numpy().squeeze()
print(pred_y, 'prediction number')
print(test_y[:10].numpy(), 'real number')

for n in range(10):
    plt.imshow(test_data.data[n].numpy(), cmap='gray')
    plt.title('data[%i' % n+']: test:%i' % test_data.targets[n]+' pred:%i' % pred_y[n])
    plt.show()

參考資料:

莫煩python的CNN小實現
PyTorch 深度學習:60分鐘快速入門(使用CIFAR10數據集實現圖像分類)
基於PyTorch的深度學習入門教程(四)——構建神經網絡
分別使用Numpy和Tensor及Antograd實現機器學習
基於PyTorch深度學習




個人彙報 ppt及演示代碼

連接:https://pan.baidu.com/s/1vZUmWc3o6BZw_6B3ArvzlA
提取碼:k0ap

連接:https://pan.baidu.com/s/1R9R_tYNerfbl71_WMZFS1w
提取碼:0rtt


最後,碼字不易,吐血整理的乾貨長文,若是有幫助的話能夠點個贊呀,給你當心心~在這裏插入圖片描述在這裏插入圖片描述

相關文章
相關標籤/搜索