Pytorch_第三篇_Pytorch Autograd (自動求導機制)


Pytorch Autograd (自動求導機制)


Introduce

Pytorch Autograd庫 (自動求導機制) 是訓練神經網絡時,反向誤差傳播(BP)算法的核心。

本文通過logistic回歸模型來介紹Pytorch的自動求導機制。首先,本文介紹了tensor與求導相關的屬性。其次,通過logistic回歸模型來幫助理解BP算法中的前向傳播以及反向傳播中的導數計算。

以下均為初學者筆記。


note: 以下用x代表創建的tensor張量。

  • x.requires_grad:True or False,用來指明該張量在反向傳播過程中是否需要求導。
  • with torch.no_grad()::當我們在做模型評估的時候是不需要求導的,可以嵌套一層with torch.no_grad()以減少可能的計算和內存開銷。
  • x.grad:返回損失函數對該張量求偏導的值,在調用backward()之后才有。
  • x.grad_fn:存儲計算圖上某中間節點進行的操作,如加減乘除等,用於指導反向傳播時loss對該節點的求偏導計算。
  • x.is_leaf:True or False,用於判斷某個張量在計算圖中是否是葉子張量。葉子張量我個人認為可以理解為目標函數中非中間因變量(中間函數、一般是運算得到的張量),如神經網絡中的權值參數w就是葉子張量(一般是手動創建的張量)。
  • x.detach():返回tensor的數據以及requires_grad屬性,且返回的tensor與原始tensor共享存儲空間,即一個改變會導致另外一個改變。因此,如果我們在backward之前對x.detach()返回的張量進行改變會導致原始x的改變,從而導致求導錯誤,但是這時系統會報錯提醒。
    (note:雖然x.data也與x.detach()作用相似,但是x.data不被Autograd系統追蹤,因此如果遇到上述問題並不會報錯。推薦使用x.detach()
  • x.item():如果張量只包含一個元素,即標量(0維張量,scalar),可以用x.item()返回,通常loss只包含一個數值,因此常用loss.item()。
  • x.tolist():如果張量只包含多個元素,可以用x.tolist()轉換成python list返回。

Build Logistic regression Model

假設有一個損失函數如下(Logistic回歸):

\[z = w1x1+w2x2+b \]

\[y_p = sigmoid(z) \]

\[Loss(y_p,y_t) = -{1\over n}\sum_{i=1}^n (y_tlog(y_p)+(1-y_t)log(1-y_p)) \]

摘自吳恩達機器學習

由損失函數構建簡單計算圖模型如下:

現在我們通過上述例子來理解前向傳播和反向傳播。在上述簡單的神經網絡模型中,我們需要對權值參數w1,w2以及閾值參數b進行更新。神經網絡訓練的總體過程如下:先由輸入層逐級前向傳播計算loss輸出,再有輸出層loss反向計算各層梯度傳播誤差,以此更新各層的權值參數w和閾值參數b。

在該模型中我們需要求出loss對w1、w2以及b的偏導,以此利用SGD更新各參數。對於根據鏈式法則的逐級求導過程不再贅述,吳恩達機器學習SGD部分有詳細的計算過程以及解釋。

現在我們利用pytorch實現logistic回歸模型,並手動實現參數更新。

import torch
import numpy as np

# 可能網絡上有許多資料在Tensor外再額外封裝一層Variable,然而從Pytorch0.4版本以后,Variable已經合並進Tensor了,因此以后的代碼可以直接用Tensor,不必要再封裝一層Variable。

# 讀入數據 x_t,y_t
x_t = torch.tensor(np.array([[1,1],[1,0],[0,1],[0,0]]),requires_grad=False,dtype=torch.float)
y_t = torch.tensor([[0],[1],[0],[1]],requires_grad=False,dtype=torch.float)
print(x_t.size())
# 定義權值參數w和閾值參數b
w = torch.randn([2,1], requires_grad=True,dtype=torch.float)
b = torch.zeros(1, requires_grad=True,dtype=torch.float)
print(w.size())
# 構建邏輯回歸模型
def logistic_model(x_t):
    a = torch.matmul(x_t,w) + b
    return torch.sigmoid(a)

y_p = logistic_model(x_t)

# 計算誤差
def get_loss(y_p, y_t):
    return -torch.mean(y_t * torch.log(y_p)+(1-y_t) * torch.log(1-y_p))

loss = get_loss(y_p, y_t)
print(loss)

# 自動求導
loss.backward()
# note:如果loss為一個標量(一般都是),那么loss.backward()不需要指定任何參數。然而如果有多個損失,即loss為一個向量tensor([loss1, loss2,loss3]),則需要指定一個gradient參數,它是與loss形狀匹配的張量,如tensor([1.0,1.0,0.1]),里面數字我個人理解為代表各損失的權重。

# 查看 w 和 b 的梯度
print(w.grad)
print(b.grad)

# 更新一次參數
w.data = w.data - 1e-2 * w.grad.data
b.data = b.data - 1e-2 * b.grad.data

'''
note:
存在兩個問題:
1. 如果沒有前面先更新一次參數,后面直接進行迭代更新的話,會報錯,具體原因也沒搞懂。
2. 利用pycharm運行pytorch代碼,調用了backward()之后,程序運行完成進程並不會終止,需要手動到任務管理器中kill進程,具體原因也不清楚。
'''

# epoch
for e in range(10000):  # 進行 10000 次更新
    y_p = logistic_model(x_t)
    loss = get_loss(y_p, y_t)

    w.grad.zero_()  # 歸零梯度
    b.grad.zero_()  # 歸零梯度
    loss.backward()

    w.data = w.data - 1e-2 * w.grad.data  # 更新 w
    b.data = b.data - 1e-2 * b.grad.data  # 更新 b
    print('epoch: {}, loss: {}'.format(e, loss.data.item()))

print(w)
print(b)

'''
每500次迭代打印出輸出結果,我們看到損失函數在迭代中逐步下降:
epoch: 0, loss: 0.9426676034927368
epoch: 500, loss: 0.5936437249183655
epoch: 1000, loss: 0.4318988025188446
epoch: 1500, loss: 0.33194077014923096
epoch: 2000, loss: 0.265964150428772
epoch: 2500, loss: 0.22003984451293945
epoch: 3000, loss: 0.18663322925567627
epoch: 3500, loss: 0.1614413857460022
epoch: 4000, loss: 0.14187511801719666
epoch: 4500, loss: 0.12630191445350647
epoch: 5000, loss: 0.11365044862031937
epoch: 5500, loss: 0.10319262742996216
epoch: 6000, loss: 0.09441888332366943
epoch: 6500, loss: 0.08696318417787552
epoch: 7000, loss: 0.08055643737316132
epoch: 7500, loss: 0.07499672472476959
epoch: 8000, loss: 0.07013023644685745
epoch: 8500, loss: 0.06583743542432785
epoch: 9000, loss: 0.06202460825443268
epoch: 9500, loss: 0.05861698091030121
至此,手動實現梯度下降,logistic模型搭建完成,之后將嘗試利用pytorch框架搭建神經網絡。

'''


本文參考-1

本文參考-2


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM