torch.autograd.Variable是Autograd的核心類,它封裝了Tensor,並整合了反向傳播的相關實現
Varibale包含三個屬性:
- data:存儲了Tensor,是本體的數據
- grad:保存了data的梯度,本事是個Variable而非Tensor,與data形狀一致
- grad_fn:指向Function對象,用於反向傳播的梯度計算之用
data
import torch as t from torch.autograd import Variable x = Variable(t.ones(2, 2), requires_grad = True) x # 實際查詢的是.data,是個Tensor
實際上查詢x和查詢x.data返回結果一致,
Variable containing:
1 1
1 1
[torch.FloatTensor of size 2x2]
梯度求解
構建一個簡單的方程:y = x[0,0] + x[0,1] + x[1,0] + x[1,1],Variable的運算結果也是Variable,但是,中間結果反向傳播中不會被求導()
這和TensorFlow不太一致,TensorFlow中中間運算果數據結構均是Tensor,
y = x.sum() y """ Variable containing: 4 [torch.FloatTensor of size 1] """
可以查看目標函數的.grad_fn方法,它用來求梯度,
y.grad_fn """ <SumBackward0 at 0x18bcbfcdd30> """ y.backward() # 反向傳播 x.grad # Variable的梯度保存在Variable.grad中 """ Variable containing: 1 1 1 1 [torch.FloatTensor of size 2x2] """
grad屬性保存在Variable中,新的梯度下來會進行累加,可以看到再次求導后結果變成了2,
y.backward() x.grad # 可以看到變量梯度是累加的 """ Variable containing: 2 2 2 2 [torch.FloatTensor of size 2x2] """
所以要歸零,
x.grad.data.zero_() # 歸零梯度,注意,在torch中所有的inplace操作都是要帶下划線的,雖然就沒有.data.zero()方法 """ 0 0 0 0 [torch.FloatTensor of size 2x2] """
對比Variable和Tensor的接口,相差無兩,
Variable和Tensor的接口近乎一致,可以無縫切換 x = Variable(t.ones(4, 5)) y = t.cos(x) # 傳入Variable x_tensor_cos = t.cos(x.data) # 傳入Tensor print(y) print(x_tensor_cos) """ Variable containing: 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 [torch.FloatTensor of size 4x5] 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 0.5403 [torch.FloatTensor of size 4x5] """