3-梯度下降和反向传播:能改

声明

本文章基于哔哩哔哩付费课程《小白也能听懂的人工智能原理》仅供学习记录、分享,严禁他用!!如有侵权,请联系删除

目录

一、内容讲解

(一)问题背景

(二)知识引入

1、求解斜率(求导)

(1)定义法

① 极限

(2)求导公式和法则

2、梯度下降

(3)梯度下降

(5)梯度下降的优势

① 批量梯度下降

② 随机梯度下降

③ mini 批量梯度下降

3、完善预测函数 + 新●梯度下降

(1)代入b后的代价函数

 (2)曲面最低点

① e和b的关系

(3)前向传播

(4)代价函数

(5)反向传播

(6)梯度下降

  (7)训练 or 学习

二、编程实验

(一)随机梯度下降

(二)批量梯度下降

(三)引入b后绘制代价函数曲面

1、豆豆数据

2、初始预测函数图像

​编辑 

 3、绘制误差e和w形成的函数图像

 4、生成不同的b值带入计算

 5、将图形转化为三维图形

(四)在w和b两个方向上分别求导,得到曲面某点的梯度进行梯度下降,拟合数据

1、e对w进行求导

2、e对b进行求导

3、代码实现


一、内容讲解

(一)问题背景

        一步到位的求解方式固然是好,但在输入特征过多、样本数量过大时却非常消耗计算资源

        抛物线最低点的寻找过程不必一步到位,大可以采用一点点挪动的方式。在最低点的左边,需要将w不断调大;在最低点右边时,需要不断将w缩小

        实现方式:斜率

        一个开口向上的抛物线,最低点斜率=0;最低点左边的斜率为负数;最低点右边的斜率为正数。通过斜率不断调整w。

        想办法得到代价函数在当前w取值这个点上的斜率。就可以判断当前w的取值是在最低点的左边or右边。然后不断调整w直到到达最低点。也就是说,得到一个误差代价最小的w。

(二)知识引入

1、求解斜率(求导)

(1)定义法

        当我们不断放小曲线上的点时,当足够小的时候,显而易见的曲线是直的。这种“直”是宏观的“弯曲”在微观中的一种近似。求解直线的斜率:

        既然在使用直线的方式计算斜率,就需要保证两点之间的距离足够小,以保证足够近似一条直线。

① 极限

        在曲线上取一个距离无限接近的点的时候,用直线斜率计算出的方法才能成为真实斜率

② 导数

        曲线中,某处的斜率。纵坐标的差值 / 横坐标的差值,并取极限

(2)求导公式和法则

2、梯度下降

        通过斜率来调整w,希望离最低点较远时,w调整速度可以快一点;而逐渐接近最低点时,希望它慢下来。这样就既能加快下降的速度,又能在最低点稳如老狗

        距离最低点越远的地方斜率最大的越大,而越近的地方越小。

        斜率在最低点左右的符号又不同

(1)所以:

新w = w - 斜率的值

  • 当w在最低点右边时斜率为正数w减去一个正数向调整
  •  当w在最低点左边时斜率是负数w减去一个负数向调整
  • 同时也做到了距离最低点较远时,斜率较大(绝对值),调整得多比较近时,斜率较小(绝对值),调整得少

(2)考虑给斜率也乘以一个比较小的学习率α来减小震荡

新w = w - α * 斜率

(3)梯度下降

        根据曲线不同处“斜率”去调整w的方式。

  • 梯度比斜率的范围更加广泛,同样适用于多维情况。

(4)“Rosenblatt感知器”模型正好是一个方差代价函数的斜率(除以2)的结果,和梯度下降如出一辙。

(5)梯度下降的优势
  • 单个豆豆情况时:它的代价函数是一个开口向上的抛物线,每个样本都是。
  • 所有样本合在一起:代价函数仍然是一个开口向上的抛物线。
    • 合成代价函数的最低点,是整个样本的全局最优点
① 批量梯度下降

        直接使用全部样本(合成总代价函数)进行梯度下降,下降的过程是一个明确且顺滑的轨迹,是标准的梯度下降

优点:并行计算、且更容易向全局最优点收敛

缺点:数据量过大时,和正规方程没有区别

② 随机梯度下降

        如果每次只使用1个样本这个样本的最低点不一定是全局最优,如果我们不断地依次在这些单样本代价函数上进行梯度下降,虽然会有震荡和波动,但多次之后它们的整体趋势仍然会向全局最优点挪动,最后也可成功。

        其收敛的过程是一个随机震荡的轨迹,称之为“随机梯度下降”

优点:海量数据也可以慢慢来

缺点:无法并行计算,且不容易向全局最优点收敛

③ mini 批量梯度下降

        批量与随机梯度下降的折中、调和

        每次选择全体样本中的一小批

3、完善预测函数 + 新●梯度下降

        当前的预测函数是危险且不完善的,更糟糕的情况是:在另一片海域中,豆豆越大,毒性越低。当前的预测函数完全不能满足上面的情况。y = wx很明显是一个必须经过原点的直线,预测函数直线的自由度被限制,只能旋转而不能移动

        一个直线完整的表达式应为:y = wx + b(截距参数)。b可以让直线在平面内自由的平移,斜率w让直线自由的旋转。二者结合,才能让直线在平面内真正自由起来。

(1)代入b后的代价函数
  • 单个豆豆

(2)b的取值对代价函数的影响

        将代价函数的图像,从二维 --> 三维,给b留出一个维度        

        b的改变只影响抛物线的一次项系数和常数项系数。b的变化只会改变抛物线的具体样子,而不会改成其他形状

        b变化后,将抛物线的形状集中在一起,变成了三维空间中的曲面。碗状曲面

 (2)曲面最低点

        每次取不同的w和b,都会导致误差e不相同。曲面最低点意味着:这里的w和b的取值,会让预测的误差(代价)最小。如果放回预测函数中,那么预测效果也是最好的。

        在没有b出现时(即b=0时),形成e和w的开口向上的抛物线。但此刻曲线的最低点 ≠ 曲面的最低点。即,b=0的取值,并不是最好的。

① e和b的关系

        当把w看作一个确定值时,e和b的关系为一个标准的开口向上的一元二次函数

        

        所以,对于形成的曲面,我们也可以理解为:e关于b的一元二次函数曲线,在w取不同值时形成的。

        现在,我们要对b 和 w进行不断调整,让它向曲线的最低点挪动,根据斜率进行下降,大小为:

斜率 * α,方向根据斜率的正负确定。

          把2个方向上的调整运动,整合成一个合成的调整运动。反复进行这个过程,也就逐渐向曲面的最低点挪动。

        当前,代价函数已经变成了一个曲面。我们在代价函数的w和b两个方向上分别求得斜率。首先偏向w进行求导:\frac{de}{dw};再偏向b求导:\frac{de}{db}(莱布尼兹求导符号:y对x的导数-->\frac{dy}{dx})。为了区分只有一个自变量的情况,把在某一变量上的导数也称之为“偏导数”

        沿着合向量进行下降,是这个曲面在该点下降最快的方式。 这个合向量在数学里称之为“梯度”,代表这个点下降最快的方向。即为梯度下降。

(3)前向传播

        将统计观测得来的数据,送入预测函数进行预测的过程。因为计算从前往后。

(4)代价函数

        通过前向传播得到一个预测值,预测值和统计观测而来的真实值之间存在着误差,利用方差(平方误差简写)差作为误差的评估手段,发现:误差和预测函数中的参数又会形成一种函数关系,称之为代价函数。也称为“方差代价函数”。

        描述了预测函数的参数取不同值时,预测的不同的误差代价

(5)反向传播

        利用代价函数去修正预测函数参数的过程。因为计算从后往前

(6)梯度下降

        反向传播参数的修正方法。

  (7)训练 or 学习

        不断经历前向传播和反向传播,最后到达代价函数的最低点的过程。

二、编程实验

(一)随机梯度下降

import dataset
import matplotlib
from matplotlib import pyplot as plt
# 首先要知道 matplotlib 的 backend 使用的是默认配置 agg (agg不能显示绘制的图),要想显示绘制的图需要更改 agg 为 TkAgg
matplotlib.use('TkAgg')

# 生成数据
xs, ys = dataset.get_beans(100)

# 配置图像
plt.title("Size-Toxicity Function", fontsize = 12) # 设置图像名称
plt.xlabel("Bean Size") # 设置横坐标的名字
plt.ylabel("Toxicity") # 设置纵坐标的名字

# 散点图
plt.scatter(xs, ys)

# 给定一个权重初始值
w = 0.1

for i in range(100):
    x = xs[i]
    y = ys[i]
    # 代价函数的相关参数为:
    # e = (y - w * x)^2 = x^2 * w^2 + (-2x * y) * w + y^2
    # a = x^2
    # b = -2 * x * y
    # c = y^2
    # 斜率:k = 2aw + b
    k = 2 * (x ** 2) * w + (-2 * x * y)
    alpha = 0.1 # 学习率,防止震荡
    w = w - alpha * k # 梯度下降调整权重w

    # plt.clf()函数清除绘图窗口
    plt.clf()
    # 重新绘制散点图和预测曲线
    plt.scatter(xs, ys)
    # 绘制预测曲线需要重新计算预测值
    y_pre = w * xs
    plt.plot(xs, y_pre)
    # 暂停函数
    plt.pause(0.01) # 暂停0.01秒

(二)批量梯度下降

        利用整体样本的代价函数来做梯度下降,主要需要使用Numpy库的sum求和函数

k = 2 * np.sum(xs**2) * w + np.sum(-2 * xs * ys)

k = k / 100

import dataset
import numpy as np
import matplotlib
from matplotlib import pyplot as plt
# 首先要知道 matplotlib 的 backend 使用的是默认配置 agg (agg不能显示绘制的图),要想显示绘制的图需要更改 agg 为 TkAgg
matplotlib.use('TkAgg')

# 生成数据
xs, ys = dataset.get_beans(100)

# 配置图像
plt.title("Size-Toxicity Function", fontsize = 12) # 设置图像名称
plt.xlabel("Bean Size") # 设置横坐标的名字
plt.ylabel("Toxicity") # 设置纵坐标的名字

# 散点图
plt.scatter(xs, ys)

# 给定一个权重初始值
w = 0.1

for _ in range(100):
    # 代价函数的相关参数为:
    # e = (y - w * x)^2 = x^2 * w^2 + (-2x * y) * w + y^2
    # a = x^2
    # b = -2 * x * y
    # c = y^2
    # 斜率:k = 2aw + b
    k = 2 * np.sum(xs**2) * w + np.sum(-2 * xs * ys)
    k = k / 100 # 代价函数是求和得到,实际上具有样本数量个曲线
    alpha = 0.1 # 学习率,防止震荡
    w = w - alpha * k # 梯度下降调整权重w

y_pre = w * xs
plt.plot(xs, y_pre)
plt.show()

(三)引入b后绘制代价函数曲面

1、豆豆数据

2、初始预测函数图像

w = 0.1;b = 0.1

y_pre = w * wx + b

 

 3、绘制误差e和w形成的函数图像

import dataset
import numpy as np
import matplotlib
from matplotlib import pyplot as plt
# 首先要知道 matplotlib 的 backend 使用的是默认配置 agg (agg不能显示绘制的图),要想显示绘制的图需要更改 agg 为 TkAgg
matplotlib.use('TkAgg')

# 获取100个豆豆的数据
xs, ys = dataset.get_beans(100)

# 绘制平面直角坐标系
# 坐标系名称 与 字体大小
plt.title("Size-Toxicity Function", fontsize=12)
# 设置坐标轴名称
plt.xlabel("Bean Size") # 豆豆大小
plt.ylabel("Bean Toxicity") # 豆豆毒性
# 设置坐标系的刻度范围
plt.xlim(0, 1)
plt.ylim(0, 1.5)

# 豆豆数量
num = 100

# 编写预测函数
# 设定初始值
w = 0.1
b = 0.1
y_pre = w * xs + b
plt.show()

# 调整w
ws = np.arange(-1, 2, 0.1)
es = []
for w in ws:
    y_pre = w * xs + b
    # 计算全部样本的均方误差
    e = np.sum((ys - y_pre) ** 2) * (1 / num)
    es.append(e)

plt.plot(ws, es)
plt.show()

 4、生成不同的b值带入计算

import dataset
import numpy as np
import matplotlib
from matplotlib import pyplot as plt
# 首先要知道 matplotlib 的 backend 使用的是默认配置 agg (agg不能显示绘制的图),要想显示绘制的图需要更改 agg 为 TkAgg
matplotlib.use('TkAgg')

# 获取100个豆豆的数据
xs, ys = dataset.get_beans(100)

# 绘制平面直角坐标系
# 坐标系名称 与 字体大小
plt.title("Size-Toxicity Function", fontsize=12)
# 设置坐标轴名称
plt.xlabel("Bean Size") # 豆豆大小
plt.ylabel("Bean Toxicity") # 豆豆毒性
# 设置坐标系的刻度范围
plt.xlim(0, 1)
plt.ylim(0, 1.5)


# 豆豆数量
num = 100

# 编写预测函数
w = 0.1
b = 0.1
y_pre = w * xs + b
plt.show()

ws = np.arange(-1, 2, 0.1)
# 生成不同的b值
bs = np.arange(-2, 2, 0.1)

for b in bs:
    es = []
    for w in ws:
        y_pre = w * xs + b
        # 计算全部样本的均方误差
        e = np.sum((ys - y_pre) ** 2) * (1 / num)
        es.append(e)
    # b取不同值时的图像
    plt.plot(ws, es)

plt.show()

 5、将图形转化为三维图形

from mpl_toolkits.mplot3d import Axes3D
import dataset
import numpy as np
import matplotlib
from matplotlib import pyplot as plt
# 导入3D坐标,进行3D绘图
from mpl_toolkits.mplot3d import Axes3D
# 首先要知道 matplotlib 的 backend 使用的是默认配置 agg (agg不能显示绘制的图),要想显示绘制的图需要更改 agg 为 TkAgg
matplotlib.use('TkAgg')

# 获取100个豆豆的数据
xs, ys = dataset.get_beans(100)

# 绘制平面直角坐标系
# 坐标系名称 与 字体大小
plt.title("Size-Toxicity Function", fontsize=12)
# 设置坐标轴名称
plt.xlabel("Bean Size") # 豆豆大小
plt.ylabel("Bean Toxicity") # 豆豆毒性
# 设置坐标系的刻度范围
plt.xlim(0, 1)
plt.ylim(0, 1.5)

# 豆豆数量
num = 100

# 编写预测函数
w = 0.1
b = 0.1
y_pre = w * xs + b


# 得到plt的图形对象,创建一个新的图形窗口
fig = plt.figure()
# 创建3D对象,添加三维坐标轴
ax = Axes3D(fig)
# 限制垂直方向(b)的取值范围
ax.set_zlim(0, 2)

ws = np.arange(-1, 2, 0.1)
bs = np.arange(-2, 2, 0.01)

for b in bs:
    es = []
    for w in ws:
        y_pre = w * xs + b
        # 计算全部样本的均方误差
        e = np.sum((ys - y_pre) ** 2) * (1 / num)
        es.append(e)

    # 改成3D的plot函数
    # 可以接受第三个维度(b)的参数
    # 正常的三维坐标,x和z在下,y朝上;但Axes3D中的三维坐标x和y在下,z朝上
    # zdir='y' 表示 y 轴被视为垂直于绘制平面的轴,因此曲线将在 x-z 平面上绘制,而 y 值将用于确定曲线在 y 轴方向上的位置。
    ax.plot(ws, es, b, zdir='y')

plt.show()

(四)在w和b两个方向上分别求导,得到曲面某点的梯度进行梯度下降,拟合数据

1、e对w进行求导

2、e对b进行求导

 

3、代码实现

import dataset
import matplotlib
from matplotlib import pyplot as plt
# 首先要知道 matplotlib 的 backend 使用的是默认配置 agg (agg不能显示绘制的图),要想显示绘制的图需要更改 agg 为 TkAgg
matplotlib.use('TkAgg')

# 生成数据
xs, ys = dataset.get_beans(100)
num = 100

# 配置图像
plt.title("Size-Toxicity Function", fontsize = 12) # 设置图像名称
plt.xlabel("Bean Size") # 设置横坐标的名字
plt.ylabel("Toxicity") # 设置纵坐标的名字

# 散点图
plt.scatter(xs, ys)

# 给定一个权重初始值
w = 0.1
b = 0.1
y_pre = w * xs + b

# 在全部样本上做了500次梯度下降
for _ in range(500):
    for i in range(100):
        x = xs[i]
        y = ys[i]

        # 对b和w进行求导,二者合在一起,才算完成一次梯度下降
        # 对w进行求导
        dw = 2 * x ** 2 * w + 2 * x * b - 2 * x * y
        # 对b进行求导
        db = 2 * b + 2 * x * w - 2 * y
        alpha = 0.01 # 学习率,防止震荡
        w = w - alpha * dw # 梯度下降调整权重w
        b = b - alpha * db # 梯度下降调整截距b

    # plt.clf()函数清除绘图窗口
    plt.clf()
    # 重新绘制散点图和预测曲线
    plt.scatter(xs, ys)
    # 绘制预测曲线需要重新计算预测值
    y_pre = w * xs + b
    plt.plot(xs, y_pre)
    # 暂停函数
    plt.pause(0.01) # 暂停0.01秒

 

  • 25
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Star_KeyW

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值