一、前向传播与反向传播的区别
前向传播是在参数固定后,向公式中传入参数,进行预测的一个过程。当参 数值选择的不恰当时,会导致最后的预测值不符合我们的预期,于是我们就 需要重新修改参数值。
在前向传播实验中时,我们都是通过手动修改w值来使直线能更好的拟合散点。
反向传播是在前向传播后进行的,它是对参数进行更新的一个过程,反向传 播的过程中参数会根据某些规律修改从而改变损失函数的值。
二、损失函数
三、梯度下降
在机器学习中,对于很多监督学习模型,需要对原始的模型构建损失函数 J,接下来便是通过优化算法对损失函数J进行优化,最小化损失函数,以便寻找到最优的参数theta.
于是,基于搜索的梯度下降法就产生了。
梯度下降法的含义是通过当前点的梯度(偏导数)的反方向寻找到新的迭代点,并从当前点移动到新的迭代点继续寻找新的迭代点,直到找到最优解。
假设你在一个陌生的山地上,你想找到一个谷底,那么肯定是想沿着向下的坡行走,如果想尽快的走到 谷底,那么肯定是要沿着最陡峭的坡下山。每走一步,都找到这里位置最陡峭的下坡走下一步,这就是 梯度下降。
在这个比喻中,梯度就像是山上的坡度,告诉我们在当前位置上地势变化最快的方向。为了尽快走向谷 底,我们需要沿着最陡峭的坡向下行走,而梯度下降算法正是这样的方法。
每走一步,我们都找到当前位置最陡峭的下坡方向,然后朝着该方向迈进一小步。这样,我们就在梯度 的指引下逐步向着谷底走去,直到到达谷底(局部或全局最优点)。
在机器学习中,梯度表示损失函数对于模型参数的偏导数。具体来说,对于每个可训练参数,梯度告诉 我们在当前参数值下,沿着每个参数方向变化时,损失函数的变化率。通过计算损失函数对参数的梯 度,梯度下降算法能够根据梯度的信息来调整参数,朝着减少损失的方向更新模型,从而逐步优化模 型,使得模型性能更好。
3.1、固定值法
3.2、小固定值
3.3、小固定值*斜率法
斜率法的优点是其更新的方向明确,就是梯度的方向,但是当斜率值过大时,会不受控制。于是为了解 决斜率法的弊端,就提出了上面对斜率值的大小进行限制的方法,通过一个小固定值*斜率,使w每次更 新的幅度不会太大,从而保证能够使w能向正确的方向更新。
在第三个式子中,小固定值被称为学习率,通过改变学习率的值能调整w的更新速度,而整个式子就叫 做梯度下降(Gradient Descent,GD),是一种优化函数,作用是降低损失。 于是,我们可以在输入一套参数后,令模型在反向传播的过程中通过梯度下降的方式来更新参数,使损 失函数值变小,从而使其能够更加准确的描述植物的环境温度与其生长高度的关系。
3.4、学习率和梯度下降
在机器学习中,学习率是一个超参数,用于控制权重更新的速度。通常来说,学习率越大,参数更新就 越快,模型就越快学习,但如果学习率过大,模型可能会不稳定,甚至无法收敛到最优解。因此,确定 一个合适的学习率是非常重要的。
梯度下降是机器学习中一种常用的优化算法。它的基本思想是在训练过程中通过不断调整参数,使损失 函数(代表模型预测结果与真实结果之间的差距)达到最小值。为了实现这一目标,梯度下降算法会计 算损失函数的梯度(带方向的斜率),然后根据梯度的方向更新权重,使损失函数不断减小。
对于一个模型来说,我们可以计算每一个权重对损失函数的影响程度,然后根据损失函数的梯度来更新 这些权重。一般来说,如果梯度是负的,那么我们就需要增加权重的值,反之,如果梯度是正的,我们 就需要减小权重的值。通过不断重复这一过程,我们就可以找到一组使损失函数最小的权重值,从而训 练出一个优秀的模型。
四、设计思路
模块导入
import numpy as np
import matplotlib.pyplot as plt
数据聚集输入
data = np.array([[0.8,1.0],[1.7,0.9],[2.7,2.4],[3.2,2.9],[3.7,2.8],[4.2,3.8],[4.2,2.7]])
#将特征和标签(需要拟合的目标)分离
x_data=data[:,0]
y_data=data[:,1]
前向计算
w_old=2
w_new=0
b=0
y_hat=w_old*x_data+b
#学习率
learning=0.01
单点误差
e=y_data-y_hat
均方误差(损失函数)
e_=(np.mean((y_data-y_hat)**2))
图像绘制
批量梯度下降法
w_new=w_old-0.5
随机梯度下降法
w_new=w_old*K
小批量梯度下降法
w_new=w_old-K*learning
fig=plt.figure(figsize=(10,5))
ax1=fig.add_subplot(1,2,1)
ax2=fig.add_subplot(1,2,2)for i in range(5):ax1.cla()ax2.cla()#k=1/n(2*w)*x**2-1/n(xy)K=2*w_old*np.mean(x_data**2)-2*np.mean(x_data*y_data)y_hat = w_new * x_data + be_=np.mean(y_hat-y_data)**2w_values = np.linspace(-10, 10, 200) # w 取值范围e_values = [np.mean(y_data - (w_value * x_data + b)) ** 2 for w_value in w_values]ax1.set_xlim(-10, 10)ax1.set_ylim(-800, 800)ax1.set_xlabel("w")ax1.set_ylabel("e")ax1.set_title("Loss Function")ax1.plot(w_values, e_values, color='g', linewidth=2) # 绘制损失函数曲线ax1.plot(w_old, e_, marker='o', markersize=8, color='r') # 标记当前 w 值对应的损失# 计算切线斜率和截距tangent_point = np.mean((y_data - (w_old * x_data + b)) ** 2) # 在 w_old 处对应的损失tangent_slope = -2 * np.mean(x_data * y_data) + 2 * w_old * np.mean(x_data ** 2) # 切线的斜率为损失函数在 w_old 处的导数tangent_intercept = tangent_point - tangent_slope * w_old # 切线的截距# 绘制切线tangent_line = tangent_slope * w_values + tangent_interceptax1.plot(w_values, tangent_line, color='b', linestyle='--') # 绘制切线# 右侧子图:散点和拟合直线ax2.set_xlim(0, 7)ax2.set_ylim(-15, 15)ax2.set_xlabel("x axis label")ax2.set_ylabel("y axis label")ax2.scatter(x_data, y_data, color='b') # 绘制训练数据散点图y_lower_lr = w_old * 0 + by_upper_lr = w_old * 5 + bax2.plot([0, 7], [y_lower_lr, y_upper_lr], color='r', linewidth=3) # 绘制线性回归直线ax2.set_title("Data Scatter and Fitted Line")# 批量梯度下降法# w_new=w_old-0.5# # 随机梯度下降法# w_new=w_old*K# # 小批量梯度下降法w_new=w_old-K*learningw_old = w_newplt.pause(1)
plt.show()
完整代码
import numpy as np # 导入 NumPy 库用于数值计算
import matplotlib.pyplot as plt # 导入 Matplotlib 库用于数据可视化 # 1. 数据聚集输入
data = np.array( # 定义一个包含 x 和 y 数据点的 NumPy 数组 [ [0.8, 1.0], [1.7, 0.9], [2.7, 2.4], [3.2, 2.9], [3.7, 2.8], [4.2, 3.8], [4.2, 2.7] ])
# 将特征和标签(需要拟合的目标)分离
x_data = data[:, 0] # 提取 x 数据作为特征
y_data = data[:, 1] # 提取 y 数据作为标签 # 2. 前向计算 y = w * x + b
w_old = 2 # 初始化旧的权重(斜率)
w_new = 0 # 初始化新的权重
b = 0 # 初始化偏置(截距)
y_hat = w_old * x_data + b # 计算预测值 # 学习率
learning = 0.01 # 定义学习率,用于更新权重 # 3. 单点误差
e = y_data - y_hat # 计算每个数据点的误差(真实值与预测值之差) # 4. 均方误差(损失函数)
e_ = (np.mean((y_data - y_hat) ** 2)) # 计算均方误差(MSE) # 5. 图像绘制
fig = plt.figure(figsize=(10, 5)) # 创建一个图形对象,设置图形尺寸
ax1 = fig.add_subplot(1, 2, 1) # 左侧子图
ax2 = fig.add_subplot(1, 2, 2) # 右侧子图 # 进行多次迭代以展示梯度下降过程
for i in range(5): ax1.cla() # 清除左侧子图内容 ax2.cla() # 清除右侧子图内容 # 计算梯度 K(损失函数的导数) K = 2 * w_old * np.mean(x_data ** 2) - 2 * np.mean(x_data * y_data) # K 为损失函数对 w 的导数 y_hat = w_new * x_data + b # 更新预测值 e_ = np.mean(y_hat - y_data) ** 2 # 计算当前 w_new 的均方误差(损失) w_values = np.linspace(-10, 10, 200) # 创建一个从 -10 到 10 的权重值数组 e_values = [np.mean(y_data - (w_value * x_data + b)) ** 2 for w_value in w_values] # 计算不同 w 值对应的均方误差 # 图像装饰 ax1.set_xlim(-10, 10) # 设置 x 轴范围 ax1.set_ylim(-800, 800) # 设置 y 轴范围 ax1.set_xlabel("w") # x 轴标签 ax1.set_ylabel("e") # y 轴标签 ax1.set_title("Loss Function") # 子图标题 ax1.plot(w_values, e_values, color='g', linewidth=2) # 绘制损失函数曲线 ax1.plot(w_old, e_, marker='o', markersize=8, color='r') # 标记当前 w 值对应的损失 # 计算切线的斜率和截距 tangent_point = np.mean((y_data - (w_old * x_data + b)) ** 2) # 在 w_old 处的损失值 tangent_slope = -2 * np.mean(x_data * y_data) + 2 * w_old * np.mean(x_data ** 2) # 切线的斜率 tangent_intercept = tangent_point - tangent_slope * w_old # 切线的截距 # 绘制切线 tangent_line = tangent_slope * w_values + tangent_intercept # 计算切线方程 ax1.plot(w_values, tangent_line, color='b', linestyle='--') # 绘制切线 # 右侧子图:散点和拟合直线 ax2.set_xlim(0, 7) # 设置 x 轴范围 ax2.set_ylim(-15, 15) # 设置 y 轴范围 ax2.set_xlabel("x axis label") # x 轴标签 ax2.set_ylabel("y axis label") # y 轴标签 ax2.scatter(x_data, y_data, color='b') # 绘制训练数据散点图 y_lower_lr = w_old * 0 + b # 拟合线在 x=0 时的 y 值 y_upper_lr = w_old * 5 + b # 拟合线在 x=5 时的 y 值 ax2.plot([0, 7], [y_lower_lr, y_upper_lr], color='r', linewidth=3) # 绘制线性回归直线 ax2.set_title("Data Scatter and Fitted Line") # 子图标题 # 批量梯度下降法 # w_new = w_old - 0.5 # 随机梯度下降法 # w_new = w_old * K # 小批量梯度下降法 w_new = w_old - K * learning # 更新权重,使用计算得出的 K 和学习率 w_old = w_new # 将新的权重传递给 w_old plt.pause(1) # 暂停 1 秒以展示动画效果
plt.show() # 展示绘图结果