Pytorch相關知識介紹與應用

前言

目前機器學習框架有兩大方向,Pytorch和Tensorflow 2。對於機器學習的小白的我來說,直觀的感受是Tensorflow的框架更加傻瓜式,在這個框架下隻需要定義神經網絡的結構、輸入和輸出,然後直接使用其框架下的各種框架函數即可。而對於Pytorch來說,則使用者能操作、定義的細節更多,但與此同時使用難度也會更高。

通過各種資料也顯示,在學術研究范圍內,越來越多的人使用Pytorch,其實Tensorflow也不錯,但對於普通小白來說入手更快,應用也更快。本著全面發展,多嘗試的心態,開始Pytorch學習。

小編將從自身的理解習慣開始不斷更新這篇博文:

1.Pytorch簡介

Pytorch就是一個神經網絡框架,使用Pytorch可以跳過很多不必要的底層工作,很多通用的方法、數據結構都已經實現供我們調用,從而可以讓我們將精力集中在改進數據質量、網絡結構和評估方法上去。

使用和訓練神經網絡從思考順序上來說無非就三個階段:

1)構思神經網絡的輸入、輸出和網絡結構,其中輸入輸出非常關鍵。

2)訓練數據集(粗糙的原始數據)。

3)如何將訓練數據集轉換成神經網絡能夠接受並且能夠正確輸出的結構。

4)訓練神經網絡並進行預測。

2.Pytorch定義神經網絡的輸入輸出和結構

使用Pytorch定義神經網絡非常通用的格式:

class NN(nn.Module):
    def __init__(self):
        super(NN,self).__init__()#繼承tOrch中已經寫好的類,包含神經網絡其餘所有通用必要方法函數。
        self.flatten=nn.Flatten()#加入展平函數。
        self.net=nn.Sequential(#調用Sequential方法定義神經網絡。
            nn.Linear(100*3,100*3),
            nn.ReLU(),
            nn.Linear(100*3,100*3),
            nn.ReLU(),
            nn.Linear(100*3,27)
        )
    def forward(self,x):#自定義神經網絡的前向傳播函數,本文使用瞭正常的前向傳播函數,但最終的結果給出三個輸出。
        result=self.net(x)
        r1=result[:9]
        r2=result[9:18]
        r3=result[18:27]    
        return [r1,r2,r3]
 

到這裡基本上已經定義瞭自己的神經網絡瞭,輸入為100*3=200個數據、輸出為27個數據。那麼問題來瞭,怎麼把數據輸入進去呢?

3.Pytorch神經網絡的數據格式-tensor

對於編程小白、機器學習小白的我或者大傢來說,tensor的直接定義不好理解。

tensor表面上隻進行瞭存儲,但實際上它包含瞭很多中方法,直接使用tensor.Method()調用相關方法即可,而省去瞭自己來定義函數,再操作數據結構。並且在Pytorch進行訓練時,也會在其內部調用這些方法,所以就需要我們使用這些數據結構來作為Pytorch神經網的輸入,並且神經網絡的輸出也是tensor形式,numpy array 和 list 和 tensor 的轉換其實就是數據相同,但集成瞭不同方法的數據結構。

那麼下面就是輸入數據的定義。train_data和labels都是我們使用python方法寫出的list。

#train_data、labels都是list,經過list->ndarray->tensor的轉換過程。
train_data=torch.tensor(np.array(train_data)).to(torch.float32).to(device)
labels=torch.tensor(np.array(labels)).to(torch.float32).to(device)

4.神經網絡進行預測

使用神經網絡進行預測(前向傳播)、計算損失函數、反向傳播更新梯度

1)進行前向傳播

#train_data[0]即為訓練數據的第一條輸入數據。
prediction=model(train_data[0])

2)計算損失

#定義優化器
optim=torch.optim.SGD(model.parameters(),lr=1e-2,momentum=0.9)
# 定義自己的loss 
loss=(prediction[0]-labels[0]).sum()+(prediction[1]-labels[1]).sum()+(prediction[2]-labels[2]).sum()
#反向傳播
optim.zero_grad()#清除上一次的靜態梯度,防止累加。
loss.backward()#計算反向傳播梯度。
optim.step()#進行一次權值更新。
 

此處的計算損失和權值依據輸入數據更新一次的結果,由此加入一個循環,便可以實現神經網絡的訓練過程。

3) 訓練網絡

在正式進入訓練網絡之前,我們還需要瞭解一個叫做Batch的東西,如果我們將數據一個一個送進去訓練,那麼神經網絡訓練的速度將是十分緩慢的,因此我們每次可以丟進去很多數據讓神經網絡進行預測,通過計算總體的損失就可以讓梯度更快地下降。但訓練數據有時又很巨大,所以就需要將整個訓練數據打包成一批一批的進入訓練,並重復若幹次,每訓練整個數據一次,會經歷若幹個batch,這一過程稱為一個epoch。

所以為瞭使網絡預測結果更快地收斂,即更快地訓練神經網絡,我們需要首先對數據進行打包。

import torch.utils.data as Data
bath=50#每批次大小
loader=Data.DataLoader(#制作數據集,隻能由cpu讀取
    dataset = train_data_set,
    batch_size=bath,#每批次包含數據條數
    shuffle=True,#是否打亂數據
    num_workers=1,#多少個線程搬運數據
)

然後,我們就可以進行神經網絡的訓練瞭:

pstep=2#每個多少個批次就輸出一次結果
for epoch in range(1000):
    running_loss=0.0
    for step,(inps,labs) in enumerate(loader):
        #取出數據並搬運至GPU進行計算。
        labs=labs.to(device)
        inps=inps.to(device) 
        outputs = model(inps)#將數據輸入進去並進行前向傳播
        loss=loss_fn(outputs,labs)#損失函數的定義
        optimizer.zero_grad()#清楚上一次的靜態梯度,防止累加。
        loss.backward()#反向傳播更新梯度
        optimizer.step()#進行一次優化。
        running_loss += loss.item()#不加item()會造成內存堆疊
        size=len(labs)*3
        correct=0
        #print("outputs:",outputs.argmax(-1),"\nlabs:",labs.argmax(-1))
        #逐個判斷計算準確率
        correct+=(outputs.argmax(-1)==labs.argmax(-1)).type(torch.float).sum().item()
        if step % pstep == pstep-1:    # print every 10 mini-batches
            print('[%d, %5d] loss: %.3f correct:%.3f' %
                  (epoch + 1, step + 1, running_loss / pstep,correct/size))
            if correct/size>1:#錯誤檢查
                print("outputs:",outputs.argmax(-1),"\nlabs:",labs.argmax(-1),"\ncorrect:",correct,"\nSize:",size)
            running_loss = 0.0
#保存模型
torch.save(model.state_dict(), "model.pth")
print("Saved PyTorch Model State to model.pth")

到此這篇關於Pytorch相關知識介紹與應用的文章就介紹到這瞭,更多相關Pytorch知識點內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: