文章目录
梯度下降和方向传播
1、 什么是梯度
是一个向量,导数+变化最快的方向(学习的前进方向)即多元函数参数的变化趋势。
机器学习
- 收集数据
x
,构建机器学习模型f
,得到f(x, w) = 预测值
- 判断模型好坏的方法:
loss = (预测值 - 真实值)^2
- 回归损失loss = 真实值 * log(预测值)
- 分类损失- 为了减低loss,通过调整参数w来实现
- 随机选择一个起始点v0, 通过调整w0,让loss函数取到最小值
- w的更新方法:
- 计算w的梯度 -> 导数:
- 更新w:
- 其中:
- 梯度的导数<0,则w将增加;
- 梯度的倒数>0,则w将减小。
2、 偏导的计算
2.1 常见的导数计算
导数微分:
2.2 多元函数求偏导
多元函数有着多个自变量。在求偏导过程中,对某一个自变量求导,其他自 变量当作常量即可。
3、方向传播算法
3.1 计算图和反向传播
计算图:通过图的方式来描述函数的图形。
将其绘制成计算图可表示为以下图片。进而,可清楚的看清计算的方向以及过程。
求偏导
方向传播的过程是一个上图的从右往左的过程,自变量a,b,c各自的偏导就是连线上的梯度的乘积。
4、神经网络中的方向传播
4.1 神经网络的示意图
- w1, w2……wn表示网络第n层权重;
wn[i,j]表示第n层第i个神经元,连接到第n+1层第j个神经元的权重。
4.2 神经网络的计算图
- ▽out是根据损失函数对
预测值
进行求导
得到的结果;f
函数可以理解为激活函数。
缺点
当模型打的时候,计算量会非常大。
因此,反向传播的思想就是对其中一个参数单独求梯度,之后更新,在计算下一层。
通用描述
5、pytorch中实现
5.1 向前计算
对于pytorch中的一个tensor,如果设置它的属性
.requires_grad
为True,那么它将会追踪对于该张量的所有操作。或者可以理解为,这个tensor
是一个参数,后续会被计算梯度,更新该参数。
5.1.1 计算过程
若要对x进行梯度计算,则在运算过程中,设置它的
requires_grad
为true
即可记录下前面的操作。
而grad_fn
能够组成一个计算图。
5.1.2 requires_grad和grad_fn
- 可通过该tensor的属性
.
传入True
直接修改。可使用grad_fn
查看- 若不想记录的步骤,可放在
with torch.no_grad()
中就不会对其进行梯度计算。
5.2 梯度计算
注意:
- 在输出为一个标量的情况下,我们可以调用输出tensor的backword()方法,但是在数据是一个向量的时候,调用backward()的时候还需要传入其他参数。
- 很多时候我们的损失函数都是一个标量,所以这里就不再介绍损失为向量的情况。
loss.backward()
就是根据损失函数,对参数(requires_grad=True)
的去计算他的梯度,并且把它累加保存到x.gard
,此时还并未更新其梯度requires_grad=True
不能直接转换,需要使用tensor.datach.numpy()
6、线性回归简单实现
# -*- coding: utf-8 -*-
""" @Time : 2021/5/15 17:50
@Author : XXX
@Site :
@File : Demolos.py
@Software: PyCharm
"""
import torch
import matplotlib.pyplot as plt
# 学习率
learning_rate = 0.01
# 通过随机数获取数据
x = torch.rand([400, 1])
y_true = x*2 + 0.2
# 构建俩个参数,模拟x,y
w = torch.rand([1,1], requires_grad=True)
b = torch.tensor(0, requires_grad=True, dtype=torch.float32)
for i in range(2500):
y_pre = torch.matmul(x, w) + b # 预测值
loss = (y_true-y_pre).pow(2).mean() # 均方误差
# 若w,b的grid置0, backward将在其中累积(添加)梯度。
if w.grad is not None:
w.grad.data.zero_()
if b.grad is not None:
b.grad.data.zero_()
loss.backward() # 反向传播
w.data = w.data - learning_rate*w.grad
b.data = b.data - learning_rate*b.grad
if i==1999:
print(w.data, b.data, loss)
plt.figure(figsize=(20, 8), dpi=80)
plt.scatter(x.view(-1), y_true.view(-1)) # 绘制散点图
y_pre = torch.matmul(x, w) + b
plt.plot(x.view(-1), y_pre.detach().numpy().reshape(-1))
plt.show()
运行结果