一、近似求导
def f(x):
return 3. * x ** 2 + 2. * x - 1 # 加点是为了浮点数的目的
#近视求导,x移动eps单位,也就是离自己很近的一个点的切线
def approximate_derivative(f, x, eps=1e-6): #函数 f, 变量 x, 步长 eps
return (f(x + eps) - f(x - eps)) / (2. * eps) # 近似导数公式
print(approximate_derivative(f, 1.))
偏导:
#求偏导数,其中一个数不动,对另外一个变量求导
def g(x1, x2):
return (x1 + 5) * (x2 ** 2)
def approximate_gradient(g, x1, x2, eps=1e-3):
dg_x1 = approximate_derivative(lambda x: g(x, x2), x1, eps)
dg_x2 = approximate_derivative(lambda x: g(x1, x), x2, eps)
return dg_x1, dg_x2
print(approximate_gradient(g, 2., 3.))
torch的近似求导,retain_graph就是保留计算图的意思,这样同一个图就可以进行多次反向传播:
# 声明两个tensor x1 和 x2,允许梯度计算,使用torch的自动求导上下文计算两个tensor的梯度
# 使用 torch.autograd.grad 计算 y = g(x1, x2) 的偏导数
x1 = torch.tensor([2.], requires_grad=True)
x2 = torch.tensor([3.], requires_grad=True)
y = g(x1, x2)
(dy_dx1,) = torch.autograd.grad(y, x1,retain_graph=True) # 近似求导,只求x1的偏导数
print(dy_dx1)
# 同时求导
x1 = torch.tensor([2.], requires_grad=True)
x2 = torch.tensor([3.], requires_grad=True)
y = g(x1, x2)
# 求偏导数
dy_dx1, dy_dx2 = torch.autograd.grad(y, [x1, x2])
print(dy_dx1, dy_dx2)
# 当然我们一般直接用 backward
x1 = torch.tensor([2.], requires_grad=True)
x2 = torch.tensor([3.], requires_grad=True)
y = g(x1, x2)
# 求偏导数,求梯度
y.backward()
print(x1.grad, x2.grad)
模拟梯度下降,更新w:
#模拟梯度下降算法 SGD
import torch
learning_rate = 0.3
x = torch.tensor(2.0, requires_grad=True)
for _ in range(100):
z = f(x)
z.backward()
x.data.sub_(learning_rate * x.grad) # x -= learning_rate * x.grad,这里就等价于optimizer.step()
x.grad.zero_() # x.grad -= x.grad, x.grad = 0,梯度清零
print(x)