https://blog.csdn.net/u012609509/article/details/81203436
Autograd mechanics
- autograd包爲張量上的所有操作提供了自動求導機制。
- torch.Tensor是這個包的核心類。如果設置它的屬性 .requires_grad爲True,那麼它將會追蹤對於該張量的所有操作。當完成計算後可以通過調用.backward(),來自動計算所有的梯度。這個張量的所有梯度將會自動累加到.grad屬性。
- 在運行時定義(define-by-run)。意味着反向傳播是根據代碼如何運行來決定的,並且每次迭代可以是不同的。
- 在概念上,autograd記錄了數據需要執行的所有算子,並將其根據順序放置在一個有向無環圖(DAG)=》計算圖。
- 從原理來講,autograd將計算圖表示成一種由Function對象組成的圖。在前向計算的時候,autograd同時執行算子op對應的計算,並且建立一個表示計算梯度的函數的圖。當前向計算完成時,我們將在反向回傳過程中評估這個圖,並計算梯度。
- 設置requires_grad=False的子圖將不用參與梯度計算。
比如下圖表示y=x⋅sin(x⋅a+b)的計算圖。沿着計算圖應用鏈式求導法則就可以求出梯度。
在底層實現中,PyTorch中的計算圖的每個結點都是一個Function對象,這個對象可以使用apply()進行操作。
在前向傳播過程中,Autograd一邊執行着前向計算,一邊搭建一個graph,這個graph的結點是用於計算梯度的函數,這些函數結點保存在對應Tensor的.grad_fn中;而反向傳播就利用這個graph計算梯度。
torch.nn
- 專門爲神經網絡設計的模塊化接口.
- nn構建於autograd之上,可以用來定義和運行神經網絡。
nn.Module:所有網絡的基類
torch.nn的核心數據結構是Module,它是一個抽象概念,既可以表示神經網絡中的某個層(layer),也可以表示一個包含很多層的神經網絡。無需糾結variable和tensor了,0.4版本已經將兩個類徹底合併了。
定義自已的網絡:需要繼承nn.Module類,並實現forward方法。
-
nn中十分重要的類,包含網絡各層的定義及forward方法。nn.Module實現的layer是由class Layer(nn.Module)定義的特殊類,會自動提取可學習參數nn.Parameter。
-
nn.Module的子類函數必須在構造函數中執行父類的構造函數: 自定義層Linear必須繼承nn.Module,並且在其構造函數中需調用nn.Module的構造函數,即super(Linear, self).init() 或nn.Module.init(self),推薦使用第一種用法。
-
在構造函數__init__中必須自己定義可學習的參數,並封裝成Parameter。
- 一般把網絡中具有**可學習參數的層放在構造函數__init__()**中,不具有可學習參數的層(如ReLU)可放在構造函數中,也可不放在構造函數中(而在forward中使用nn.functional來代替)
-
只要在nn.Module的子類中定義了forward函數,backward函數就會被自動實現(利用Autograd)。
- forward函數實現前向傳播過程,其輸入可以是一個或多個variable,對x的任何操作也必須是variable支持的操作。
- 無需寫反向傳播函數,因其前向傳播都是對variable進行操作,nn.Module能夠利用autograd自動實現反向傳播,這點比Function簡單許多。
-
使用時,直觀上可將layer看成數學概念中的函數,調用layer(input)即可得到input對應的結果。它等價於layers.call(input),在__call__函數中,主要調用的是 layer.forward(x),另外還對鉤子做了一些處理。所以在實際使用中應儘量使用layer(x)而不是使用layer.forward(x)。
-
Module中的可學習參數可以通過named_parameters()或者parameters()返回迭代器,前者會給每個parameter都附上名字,使其更具有辨識度。
import torch.nn as nn
import torch.nn.functional as F
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.conv1 = nn.Conv2d(1, 20, 5)# submodule: Conv2d
self.conv2 = nn.Conv2d(20, 20, 5)
def forward(self, x):
x = F.relu(self.conv1(x))
return F.relu(self.conv2(x))
Modules也可以包含其它Modules,允許使用樹結構嵌入他們。你可以將子模塊賦值給模型屬性。通過上面方式賦值的submodule會被註冊。當調用 .cuda() 的時候,submodule的參數也會轉換爲cuda Tensor。
cuda()
將所有的模型參數(parameters)和buffers賦值GPU
forward(* input)
定義了每次執行的 計算步驟。 在所有的子類中都需要重寫這個函數。
train()
將module設置爲 training mode。僅僅當模型中有Dropout和BatchNorm是纔會有影響。
zero_grad()
將module中的所有模型參數的梯度設置爲0.
load_state_dict(state_dict)
將state_dict中的parameters和buffers複製到此module和它的後代中。state_dict中的key必須和 model.state_dict()返回的key一致。 NOTE:用來加載模型參數。
torch.nn.Linear(in_features, out_features, bias=True):定義一個linear
對輸入數據做線性變換:y=Ax+b
定義一個linear層,對輸入數據做線性變換. (N, in_features) => (N, out_features)
- 輸入: (N,in_features) 輸出: (N,out_features)
- weight 形狀爲(out_features x in_features)的模塊中可學習的權值
- bias 形狀爲(out_features)的模塊中可學習的偏置。bias 若設置爲False,這層不會學習偏置。默認值:True
torch.nn.utils.clip_grad_norm(parameters, max_norm, norm_type=2)
parameters (Iterable[Variable]) – 一個基於變量的迭代器,會進行歸一化(原文:an iterable of Variables that will have gradients normalized)
max_norm (float or int) – 梯度的最大範數(原文:max norm of the gradients)
norm_type(float or int) – 規定範數的類型,默認爲L2(原文:type of the used p-norm. Can be'inf'for infinity norm)
梯度裁剪:解決梯度消失/爆炸(就是偏導無限接近0,導致長時記憶無法更新):
- 當梯度小於/大於閾值時,更新的梯度爲閾值。
- 根據參數的範數來衡量clip_grad_norm()
torch.optim:提供了基於多種epoch數目調整學習率的方法。
- 爲了使用torch.optim,你需要構建一個optimizer對象。這個對象能夠保持當前參數狀態並基於計算得到的梯度進行參數更新。
構建optimizer對象
optimizer = optimizer()
PyTorch的optimizer默認情況會自動對梯度進行accumulate[4],所以對下一次iteration(一個新的batch),需要對optimizer進行清空操作。
optimizer.step():進行單次優化 (參數更新).
- 所有的optimizer都實現了step()方法。
- 一旦梯度被如backward()之類的函數計算好後,我們就可以調用這個函數。
https://blog.csdn.net/g11d111/article/details/83035270
https://blog.csdn.net/gdymind/article/details/82224011