梯度
每个方向梯度降低,某方向可能会发生震荡
- 初始点不同,会影响找到全局最优解和局部最优解
- 学习率影响精度和速度
- 逃离局部极小值——给一个动量
激活函数
torch.sigmoid(torch.linspace(-100,100,10))
from torch.nn import functional as F
F.sigmoid(...)
tanh/relu
LOSS的梯度
回归和分类LOSS怎么选?
torch.norm(y-pred,2).pow(2)
mse = F.mse_loss(pred,x) # (pred-x)^2
w.require_grad_() # 需要更新梯度信息
torch.autograd.grad(mse,[w]) # 自动计算
x = torch.ones(1)
w = torch.full([1],2)
mse = F.mse_loss(torch.ones(1),x*w)
mse.backward()
w.grad
>>> tensor(2.)
p.backward(remain_graph=True)才能保留图,该报错是因为图已被清理
grad中的p[0]/p[1]/p[2]表示一次只能对一个变量求导,前一个是因变量,后一个是自变量
pytorch 中autograd.grad()函数的用法说明 | w3c笔记
单层感知机
x = torch.randn(1,10)
w = torch.randn(1,10,requires_grad=True)
o = torch.sigmoid(x@w.t()) # w.t() -> w的转置
loss = F.mse_loss(torch.ones(1,1),o) # 1个数值
# w = w-lr*▽σ
loss.backward() # 相当于loss对10个w求了偏导,即([[x1w1+...+x10w10]]-[[1]])^2求导
w.grad.shape
>>> 1*10
多层感知机
注意:x2与x1无关,即第二行和第一行无关
x = torch.randn(1,10)
w = torch.randn(2,10,requires_grad=True)
o = torch.sigmoid(x@w.t()) # w.t() -> w的转置
loss = F.mse_loss(torch.ones(1,2),o) # 1个数值
loss.backward() # 相当于loss对10个w求了偏导,即([[x1w1+...+x10w10]]-[[1]])^2求导
w.grad.shape
>>> 2*10
链式法则
x = torch.tensor(1.)
w1 = torch.tensor(2., requires_grad=True)
b1 = torch.tensor(1.)
w2 = torch.tensor(2., requires_grad=True)
b2 = torch.tensor(1.)
y1 = w1*x+b1
y2 = w2*y1+b2
dy1_dw1 = torch.autograd.grad(y1,[w1],retain_graph=True)[0]
>>> tensor(1.) # 不加[0]为(tensor(1.),),★都需要加0
dy2_dy1 = torch.autograd.grad(y2,[y1],retain_graph=True)[0]
dy2_dw1 = torch.autograd.grad(y2,[w1],retain_graph=True)[0]
dy2_dw1 == dy2_dy1*dy1_dw1
>>> True
推导过程:MLP多层感知机梯度推导与反向传播_NotFound1911的博客-CSDN博客
即可求得前三层的偏导数
优化实例
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import pyplot as plt
import torch
def himmelblau(x):
return (x[0] ** 2 + x[1] - 11) ** 2 + (x[0] + x[1] ** 2 - 7) ** 2
x = np.arange(-6, 6, 0.1)
y = np.arange(-6, 6, 0.1)
print('x,y range:', x.shape, y.shape)
X, Y = np.meshgrid(x, y)
print('X,Y maps:', X.shape, Y.shape)
Z = himmelblau([X, Y])
fig = plt.figure('himmelblau')
ax = fig.gca(projection='3d')
ax.plot_surface(X, Y, Z)
ax.view_init(60, -30)
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.show()
# 初始值
x = torch.tensor([-4., 0.], requires_grad=True)
optimizer = torch.optim.Adam([x], lr=1e-3)
for step in range(20000):
# 一般对损失函数进行梯度计算,这里是原始函数
pred = himmelblau(x)
optimizer.zero_grad()
pred.backward()
optimizer.step()
if step % 2000 == 0:
print ('step {}: x = {}, f(x) = {}'
.format(step, x.tolist(), pred.item()))