文章目录
一般梯度下降方法
- 损失函数
(
L
o
s
s
f
u
n
c
t
i
o
n
)
(Loss\ function)
(Loss function):计算的是一个样本的误差;
- 示例 ( y p r e d − y ) 2 (y_{pred}-y)^2 (ypred−y)2
- 代价函数
(
C
o
s
t
f
u
n
c
t
i
o
n
)
(Cost\ function)
(Cost function):计算的是训练集所有样本误差的平均值
- 示例 1 N ∑ ( y p r e d − y ) 2 \frac{1}{N}\sum(y_{pred}-y)^2 N1∑(ypred−y)2
批量梯度下降( B G D BGD BGD)
w = w − α ∂ c o s t ∂ w w = w - \alpha \dfrac{\partial cost}{\partial w} w=w−α∂w∂cost
∂ c o s t ∂ w = 1 N 2 w ( x w − y ) ; y p r e d = x w 时 \dfrac{\partial cost}{\partial w} = \frac{1}{N}2w(xw-y);\ \ \ \ \ \ y_{pred} = xw时 ∂w∂cost=N12w(xw−y); ypred=xw时
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
w = 1 # 初始值
def forward(x): # 模型
return x * w
def cost(xs, ys): # MSE
cost = 0
for x, y in zip(xs, ys):
y_pred = forward(x)
cost += (y_pred-y)**2
return cost/len(xs)
def gradient(xs, ys): # 计算梯度
grad = 0
for x,y in zip(xs,ys):
grad += 2*x*(x*w-y)
return grad/len(xs)
print('Predict (before training)', 4, forward(4))
for epoch in range(100): # 下降次数
cost_val = cost(x_data, y_data)
grad_val = gradient(x_data, y_data)
w -= 0.01 * grad_val # 梯度下降
print('Epoch:',epoch,'w=',w,'cost=',cost_val)
print('Predict (after training)',4,forward(4))
- 优点:每次都会朝着正确的方向进行,最终保证收敛到极值点
- 缺点:每次需用所有样本,更新速度慢
随机梯度下降 ( S G D ) (SGD) (SGD)
w = w − ∂ l o s s ∂ w w = w - \frac{\partial loss}{\partial w} w=w−∂w∂loss
∂ l o s s ∂ w = 2 w ( x w − y ) ; y p r e d = x w 时 \dfrac{\partial loss}{\partial w} = 2w(xw-y);\ \ \ \ \ \ y_{pred} = xw时 ∂w∂loss=2w(xw−y); ypred=xw时
import random
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
w = 1 # 初始值
def forward(x): # 模型
return x * w
def loss(x, y):
y_pred = forward(x)
return (y_pred - y) ** 2
def gradient(x, y): # 计算梯度
y_pred = forward(x)
return 2*w*(y_pred - y)
print('Predict (before training)', 4, forward(4))
for epoch in range(100): # 下降轮数
for x, y in zip(x_data, y_data):
loss_val = loss(x, y)
grad_val = gradient(x, y)
w -= 0.01 * grad_val # 梯度下降
print('Epoch:',epoch,'w=',w,'loss=',loss_val)
print('Predict (after training)',4,forward(4))
- 每次考虑一个样本点,更新速度快
- 每次更新可能不会按照正确的方向进行,可能有扰动。
- 扰动也有好处,有可能从一个局部极小值跳到另一个局部极小值
小批量梯度下降 ( M B G D ) (MBGD) (MBGD)
二者折中
小批量随机梯度下降是深度学习默认的求解算法;
其具备两个重要的超参数:批量大小和学习率;
PyTorch梯度下降方法
核心:省去梯度函数,利用tensor中的grad即可得到所需梯度 ∂ l o s s ∂ w \frac{\partial loss}{\partial w} ∂w∂loss。
import torch
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
w = torch.Tensor([1.0]) # 默认不带有梯度
w.requires_grad = True # 使w张量具有梯度
def forward(x):
return x * w # 返回值含有梯度
# 此处乘法运算符被重载,可用于Tensor的计算
def loss(x, y): # 一个样本的loss
y_pred = forward(x)
return (y_pred-y) ** 2 # 返回值含有梯度
print('Predict (before training)', 4, forward(4).item()) # item()是将Tensor中的grad计算值转换成一个标量
for epoch in range(100): # 梯度下降次数
for x,y in zip(x_data, y_data): # 要全部遍历一遍啊
l = loss(x,y) # 前向传播; 前馈的过程就是建立计算图的过程;
l.backward() # 反向传播; 求出了所有需要的梯度; 反向传播之后计算图就被释放
print('\tgrad:', x, y, w.grad.item())
# 构建时用Tensor,权重更新时用.data
w.data -= 0.01 * w.grad.data
# 引入PyTorch的grad自动求每个样本时的梯度
print('w.grad.item() ',w.grad.item())
print('w.grad.data ',w.grad.data)
w.grad.data.zero_() # 将本轮计算的grad清零,否则默认是dL/dw累加至下一轮
print('process:', epoch, l.item())
print('Predict (after training)',4,forward(4).item())