Pytorch Autograd庫 (自動求導機制) 是訓練神經網絡時,反向偏差傳播(BP)算法的核心。python
本文經過logistic迴歸模型來介紹Pytorch的自動求導機制。首先,本文介紹了tensor與求導相關的屬性。其次,經過logistic迴歸模型來幫助理解BP算法中的前向傳播以及反向傳播中的導數計算。git
如下均爲初學者筆記。github
note: 如下用x表明建立的tensor張量。算法
假設有一個損失函數以下(Logistic迴歸):網絡
由損失函數構建簡單計算圖模型以下:機器學習
如今咱們經過上述例子來理解前向傳播和反向傳播。在上述簡單的神經網絡模型中,咱們須要對權值參數w1,w2以及閾值參數b進行更新。神經網絡訓練的整體過程以下:先由輸入層逐級前向傳播計算loss輸出,再有輸出層loss反向計算各層梯度傳播偏差,以此更新各層的權值參數w和閾值參數b。函數
在該模型中咱們須要求出loss對w一、w2以及b的偏導,以此利用SGD更新各參數。對於根據鏈式法則的逐級求導過程再也不贅述,吳恩達機器學習SGD部分有詳細的計算過程以及解釋。學習
如今咱們利用pytorch實現logistic迴歸模型,並手動實現參數更新。ui
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框架搭建神經網絡。 '''