1. 程式人生 > 實用技巧 >4 pytorch基礎

4 pytorch基礎

書《深度學習之PyTorch實戰計算機視覺》第六章

這次主要記錄三部分內容:

自動梯度

  • 向後傳播自動化

自定義傳播函式

  • 重寫向前傳播和向後傳播

模型搭建和引數優化


自動梯度

實現對模型中後向傳播梯度的自動計算,後向傳播自動化(loss.backward)

torch.autograd實現後向傳播中的鏈式求導

Variable類對我們定義的Tensor資料型別進行封裝。用X代表我們選中的節點,是一個Variable物件,那麼X.data代表Tensor資料型別的變數,X.grad是Variable型別的變數,想要訪問梯度值需要使用X.grad.data

loss.backward()是後向傳播計算部分,自動計算每個節點的梯度並根據需求進行保留

import torch
from torch.autograd import Variable
batch_n = 100
hidden_layer = 100
input_data = 1000
output_data = 10

x = Variable(torch.randn(batch_n, input_data), requires_grad = False)
y = Variable(torch.randn(batch_n, output_data), requires_grad = False)

w1 = Variable(torch.randn(input_data, hidden_layer), requires_grad = True) #權重1是1000*100
w2 
= Variable(torch.randn(hidden_layer, output_data), requires_grad = True)#權重2是100*10 epoch_n = 20 learning_rate = le-6 for epoch in range(epoch_n): y_pred = x.mm(w1).clamp(min=0).mm(w2) loss = (y_pred-y).pow(2).sum() print("Epoch:{}, Loss:{:.4f}".format(epoch, loss.data[0])) loss.backward() w1.data
-=learning_rate*w1.grad.data w2.data -=learning_rate*w2.grad.data w1.grad.data.zero_() w2.grad.data.zero_()

自定義傳播函式

torch.nn.Module重寫前向傳播forward和後向傳播backward

import torch
from torch.autograd import Variable
batch_n = 100
hidden_layer = 100
input_data = 1000
output_data = 10

'''相比於前面程式碼新增部分'''
class Model(torch.nn.module):
    def __init__(self):
        super(Module, self).__init__()

    def forward(self, input, w1, w2):  #實現向前傳播矩陣運算
        x = torch.mm(x, w1)
        x = torch.clamp(x, min=0)
        x = torch.mm(x, w2)
        return x

    def backward(self):      #實現向後傳播自動梯度計算
        pass

model = Model()

'''
上面模型搭建好了,下面對模型進行訓練和引數優化
'''

x = Variable(torch.randn(batch_n, input_data), requires_grad = False)
y = Variable(torch.randn(batch_n, output_data), requires_grad = False)

w1 = Variable(torch.randn(input_data, hidden_layer), requires_grad = True)
w2 = Variable(torch.randn(hidden_layer, output_data), requires_grad = True)

epoch_n = 20
learning_rate = le-6

for epoch in range(epoch_n):
    y_pred = model(x, w1, w2)   #有改動,原來是x.mm(w1).clamp(min=0).mm(w2)
    loss = (y_pred-y).pow(2).sum()
    print("Epoch:{}, Loss:{:.4f}".format(epoch, loss.data[0]))

    loss.backward()

    w1.data -=learning_rate*w1.grad.data
    w2.data -=learning_rate*w2.grad.data

    w1.grad.data.zero_()
    w2.grad.data.zero_()


模型搭建和引數優化

torch.nn包

  • torch.nn.Sequential

  序列容器,通過巢狀各種類,實現對網路模型的搭建,引數會按照我們定義好的序列自動傳遞下去

  • torch.nn.Linear

  線性層。引數有三個,分別是輸入特徵數,輸出特徵數和是否使用偏置,偏置引數是一個布林值,預設為True,即使用偏置。

  • torch.nn.ReLU

  非線性啟用函式,在定義時預設不需要傳入引數。除此之外,還包括PReLU,LeakyReLU,Tanh,Sigmod,Softmax等。

  • 損失函式

  包括:

(1)torch.nn.MSELoss:使用均方誤差函式計算損失值

  

  (2)torch.nn.L1Loss:使用平均絕對誤差計算損失值

  

  (3)torch.nn.CrossEntropyLoss:計算交叉熵

  資訊量:它是用來衡量一個事件的不確定性的;一個事件發生的概率越大,不確定性越小,則它所攜帶的資訊量就越小。:它是用來衡量一個系統的混亂程度的,代表一個系統中資訊量的總和;資訊量總和越大,表明這個系統不確定性就越大交叉熵:它主要刻畫的是實際輸出(概率)與期望輸出(概率)的距離,也就是交叉熵的值越小,兩個概率分佈就越接近。假設概率分佈p為期望輸出,概率分佈q為實際輸出,為交叉熵,則

但是Pytorch中計算的交叉熵並不是採用上式,而是下面這個

   

torch.optim包

實現神經網路權重引數優化更新自動化。該包提供了許多方法,SGD,AdaGrad,RMSProp,Adam等。

接下來使用自動化的優化函式對前面的程式碼進行替換

import torch
from torch.autograd import Variable
#設定引數
batch_n = 100
hidden_layer = 100
input_data = 1000
output_data = 10

x = Variable(torch.randn(batch_n, input_data), requires_grad = False)
y = Variable(torch.randn(batch_n, output_data), requires_grad = False)

#構建模型
models = torch.nn.Sequential(
    torch.nn.Linear(input_data, hidden_layer),
    torch.nn.ReLU(),
    torch.nn.Linear(hidden_layer, output_data)
)
#設定超引數
epoch_n = 20
learning_rate = le-6
#定義損失函式和權重優化引數
loss_fn = torch.nn.MSELoss()
optimzer = torch.optim.Adam(models.parameters(), lr = learning_rate)

for epoch in range(epoch_n):
    y_pred = models(x) 
    loss = loss_fn(y_pred, y) #有改動 loss = (y_pred-y).pow(2).sum()
    print("Epoch:{}, Loss:{:.4f}".format(epoch, loss.data[0]))

    optimer.zero_grad() #實現模型引數梯度歸零,代替前面w1.grad.data.zero_()和w2
    loss.backward()
    optimer.step()  #實現梯度更新,代替前面w1.data -=learning_rate*w1.grad.data和w2

這一部分就記錄到這裡。