自動微分機制
Pytorch一般通過反向傳播 backward 方法 實現這種求梯度計算。該方法求得的梯度將存在對應自變量張量的grad屬性下。
除此之外,也能夠調用torch.autograd.grad 函數來實現求梯度計算。
這就是Pytorch的自動微分機制。
一,利用backward方法求導數
backward 方法通常在一個標量張量上調用,該方法求得的梯度將存在對應自變量張量的grad屬性下。
如果調用的張量非標量,則要傳入一個和它同形狀 的gradient參數張量。
相當于用該gradient參數張量與調用張量作向量點乘,得到的標量結果再反向傳播。
1, 標量的反向傳播
x = torch.tensor(0.0,requires_grad = True) # x需要被求導
#注意:這里的x是一維的
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
y = a*torch.pow(x,2) + b*x + cy.backward()
dy_dx = x.grad
print(dy_dx)
2, 非標量的反向傳播
"""
2, 非標量的反向傳播
"""
import numpy as np
import torch# f(x) = a*x**2 + b*x + cx = torch.tensor([[0.0,0.0],[1.0,2.0]],requires_grad = True) # x需要被求導
#這里的x是二維的
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
y = a*torch.pow(x,2) + b*x + cgradient = torch.tensor([[1.0,1.0],[1.0,1.0]])print("x:\n",x)
print("y:\n",y)
y.backward(gradient = gradient)
#非標量的區別在這里:相當于用該gradient參數張量與調用張量作向量點乘,得到的標量結果再反向傳播。
x_grad = x.grad
print("x_grad:\n",x_grad)
3, 非標量的反向傳播可以用標量的反向傳播實現
"""
3, 非標量的反向傳播可以用標量的反向傳播實現
"""
x = torch.tensor([[0.0,0.0],[1.0,2.0]],requires_grad = True) # x需要被求導
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
y = a*torch.pow(x,2) + b*x + cgradient = torch.tensor([[1.0,1.0],[1.0,1.0]])
z = torch.sum(y*gradient) #將Y與權值相乘然后取和print("x:",x)
print("y:",y)
z.backward()
x_grad = x.grad
print("x_grad:\n",x_grad)
二,利用autograd.grad方法求導數
利用autograd.grad方法對單個變量求導數
"""
二,利用autograd.grad方法求導數
"""
x = torch.tensor(0.0,requires_grad = True) # x需要被求導
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
y = a*torch.pow(x,2) + b*x + c# create_graph 設置為 True 將允許創建更高階的導數
dy_dx = torch.autograd.grad(y,x,create_graph=True)[0]
print(dy_dx.data)# 求二階導數
dy2_dx2 = torch.autograd.grad(dy_dx,x)[0]print(dy2_dx2.data)
利用autograd.grad方法對多個變量求導數
"""
利用autograd.grad方法對多個變量求導數
"""
x1 = torch.tensor(1.0,requires_grad = True) # x需要被求導
x2 = torch.tensor(2.0,requires_grad = True)y1 = x1*x2
y2 = x1+x2# 允許同時對多個自變量求導數
(dy1_dx1,dy1_dx2) = torch.autograd.grad(outputs=y1,inputs = [x1,x2],retain_graph = True)
print(dy1_dx1,dy1_dx2)# 如果有多個因變量,相當于把多個因變量的梯度結果求和
(dy12_dx1,dy12_dx2) = torch.autograd.grad(outputs=[y1,y2],inputs = [x1,x2])
print(dy12_dx1,dy12_dx2)
三,利用自動微分和優化器求最小值
"""
三,利用自動微分和優化器求最小值
"""x = torch.tensor(0.0,requires_grad = True) # x需要被求導
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)optimizer = torch.optim.SGD(params=[x],lr = 0.01)def f(x):result = a*torch.pow(x,2) + b*x + creturn(result)for i in range(500):optimizer.zero_grad()y = f(x)y.backward()optimizer.step()print("y=",f(x).data,";","x=",x.data)
完整代碼
import torch
import numpy as np"""
1, 標量的反向傳播
"""
x = torch.tensor(0.0,requires_grad = True) # x需要被求導
#注意:這里的x是一維的
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
y = a*torch.pow(x,2) + b*x + cy.backward()
dy_dx = x.grad
print(dy_dx)"""
2, 非標量的反向傳播
"""
import numpy as np
import torch# f(x) = a*x**2 + b*x + cx = torch.tensor([[0.0,0.0],[1.0,2.0]],requires_grad = True) # x需要被求導
#這里的x是二維的
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
y = a*torch.pow(x,2) + b*x + cgradient = torch.tensor([[1.0,1.0],[1.0,1.0]])print("x:\n",x)
print("y:\n",y)
y.backward(gradient = gradient)
#非標量的區別在這里:相當于用該gradient參數張量與調用張量作向量點乘,得到的標量結果再反向傳播。
x_grad = x.grad
print("x_grad:\n",x_grad)"""
3, 非標量的反向傳播可以用標量的反向傳播實現
"""
x = torch.tensor([[0.0,0.0],[1.0,2.0]],requires_grad = True) # x需要被求導
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
y = a*torch.pow(x,2) + b*x + cgradient = torch.tensor([[1.0,1.0],[1.0,1.0]])
z = torch.sum(y*gradient) #將Y與權值相乘然后取和print("x:",x)
print("y:",y)
z.backward()
x_grad = x.grad
print("x_grad:\n",x_grad)"""
二,利用autograd.grad方法求導數
"""
x = torch.tensor(0.0,requires_grad = True) # x需要被求導
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)
y = a*torch.pow(x,2) + b*x + c# create_graph 設置為 True 將允許創建更高階的導數
dy_dx = torch.autograd.grad(y,x,create_graph=True)[0]
print(dy_dx.data)# 求二階導數
dy2_dx2 = torch.autograd.grad(dy_dx,x)[0]print(dy2_dx2.data)
"""
利用autograd.grad方法對多個變量求導數
"""
x1 = torch.tensor(1.0,requires_grad = True) # x需要被求導
x2 = torch.tensor(2.0,requires_grad = True)y1 = x1*x2
y2 = x1+x2# 允許同時對多個自變量求導數
(dy1_dx1,dy1_dx2) = torch.autograd.grad(outputs=y1,inputs = [x1,x2],retain_graph = True)
print(dy1_dx1,dy1_dx2)# 如果有多個因變量,相當于把多個因變量的梯度結果求和
(dy12_dx1,dy12_dx2) = torch.autograd.grad(outputs=[y1,y2],inputs = [x1,x2])
print(dy12_dx1,dy12_dx2)"""
三,利用自動微分和優化器求最小值
"""x = torch.tensor(0.0,requires_grad = True) # x需要被求導
a = torch.tensor(1.0)
b = torch.tensor(-2.0)
c = torch.tensor(1.0)optimizer = torch.optim.SGD(params=[x],lr = 0.01)def f(x):result = a*torch.pow(x,2) + b*x + creturn(result)for i in range(500):optimizer.zero_grad()y = f(x)y.backward()optimizer.step()print("y=",f(x).data,";","x=",x.data)