PyTorch學習之 自動微分

PyTorch學習之 自動微分


autograd包

autograd 包是 PyTorch 中所有神經網絡的核心。該 autograd 軟件包爲 Tensors 上的所有操作提供自動微分。它是一個由運行定義的框架,這意味着以代碼運行方式定義你的後向傳播,並且每次迭代都可以不同。

Tensor的屬性設置

屬性 說明
.requires_grad = True 開始跟蹤針對 tensor 的所有操作
.backward() 自動計算所有梯度
.grad 張量的梯度將累積到其中
.deatch() 停止tensor歷史記錄的追蹤
with.torch.no_grad() 停止跟蹤歷史記錄和使用內存。在評估模型時,這是特別有用,因爲模型在訓練階段具有 requires_grad = True 的可訓練參數有利於調參,但在評估階段我們不需要梯度。

Function 類

Function類對於autograd非常重要,Tensor與Function構成一個非循環圖,它保存整個完整的計算過程的歷史信息。.grad_fn屬性保存着創建了張量的Function的引用。如果想計算導數,可以調用Tensor.backward()。
需要注意的是, 當tensor的是標量時, 不需要指定任何參數backward,但若有更多元素,則需要指定一個gradient參數來指定張量的形狀。

代碼

# -*- coding: UTF-8 -*-
"""
Modify: 2019-12-12
"""
import torch
#創建一個張量,設置requires_grad=True來跟蹤與它相關的計算
x = torch.ones(2, 2, requires_grad=True)
print(x)
#輸出
# tensor([[1., 1.],
#         [1., 1.]], requires_grad=True)

#針對張量做一個操作
y = x + 2
print(y)
#輸出
# tensor([[3., 3.],
#         [3., 3.]], grad_fn=<AddBackward0>)

#y作爲操作的結果被創建,所以它有grad_fn
print(y.grad_fn)
#輸出
#<AddBackward0 object at 0x0000023783F70588>

# 針對y做更多的操作
z = y * y *3
out = z.mean()
print(z)
print(out)
#輸出
# tensor([[27., 27.],
#         [27., 27.]], grad_fn=<MulBackward0>)
# tensor(27., grad_fn=<MeanBackward0>)

#.requires_grad(...)會改變張量的requires_grad標記
# 如果沒有提供相應的參數,輸入的標記默認爲False
a = torch.randn(2, 2)
a = (a * 3) / (a - 1)
print(a.requires_grad)
a.requires_grad_(True)
print(a.requires_grad)
b = (a * a).sum()
print(b.grad_fn)
#輸出
# False
# True
# <SumBackward0 object at 0x00000261ADB56208>


# 梯度
#因爲輸出包含了一個標量,out.backward()等同於out.backward(torch.tensor(1.))
out.backward()
#打印梯度 d(out)/dx
print(x.grad)
#輸出
# tensor([[4.5000, 4.5000],
#         [4.5000, 4.5000]])
# 下面來看一個雅可比向量積的例子
x = torch.randn(3, requires_grad=True)
y = x * 2
while y.data.norm() < 1000:    # y.data.norm(input, p=2) 求y的範數
   y = y * 2
print(y)
#輸出
#tensor([ -745.7645, -1334.8055,   385.1612], grad_fn=<MulBackward0>)

#現在在這種情況下,y 不再是一個標量。torch.autograd 不能夠直接計算整個雅可比,
#但是如果我們只想要雅可比向量積,只需要簡單的傳遞向量給 backward 作爲參數。
v = torch.tensor([0.1, 1.0, 0.0001], dtype=torch.float)
y.backward(v)
print(x.grad)
#輸出
#tensor([4.0960e+02, 4.0960e+03, 4.0960e-01])

#可以通過將代碼包裹在with torch.no_grad(),
#來停止對從跟蹤歷史中的.requires=True的張量自動求導
print(x.requires_grad)
print((x ** 2).requires_grad)
with torch.no_grad():
    print((x ** 2).requires_grad)
#輸出
# True
# True
# False
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章