梯度下降算法(Gradient Descent)
梯度下降算法在机器学习中应用十分的广泛,不论是在线性回归还是Logistic回归中,它的主要目的是通过迭代找到目标函数的最小值,或者收敛到最小值。
求下面函数的极值
y
=
x
s
i
n
(
x
)
y=xsin(x)
y=xsin(x)
可以发现在当前这个区间范围内这个函数有两个极小值点,如果我们想寻找当前函数在这个区间内的最小值点,那么当然是第二个极小值点更合适一些,可是并不一定能够如我们所愿顺利地找到第二个极小值点,这时候只能够通过多次尝试。
- 梯度的概念:梯度就是函数对它的各个自变量求偏导后,由偏导数组成的一个向量。
接着来看下一个函数
既然算法是“梯度下降法”,所以先求一下这个函数的梯度,当前的函数f(x)的梯度就是他的导数,这很简单
f ( x ) ′ = 2 x − 2 f(x)' = 2x - 2 f(x)′=2x−2
图上小红点的坐标是(6,f(6)),那么可以得到 f ( 6 ) ′ = 10 f(6)'=10 f(6)′=10
现在用导数值的正负来表示方向如果导数的值是正数,那么就代表x轴的正方向。如果导数的值是负数就代表x轴的负方向。那么就会发现知道了这个方向之后也就知道了应该让x往哪个方向变化f(x)的值减小。那么就让 朝着导数告诉我们的方向的反方向变化就好啦。
- 梯度下降法的目标:搜索出来一个能让函数值尽可能小的位置,所以让x朝着红色箭头的方向走。
代码中有一个eta变量,专业称为“学习率”。使用数学表达式来更新x的过程那就是:
x ← x − e t a ∗ d f ( x ) d x x \leftarrow x -eta*\frac{df(x)}{dx} x←x−eta∗dxdf(x)
意思是让x减去eta乘以函数的导数。其中eta是为了控制x更新的幅度,将eta的值设置小一点,那么每一次的更新的幅度就会小一点。
代码实现
import numpy as np
import matplotlib.pyplot as plt
# 定义 x 的范围
x = np.linspace(-7, 9, 400) # 从 -7 到 9,总共 400 个点
y = (x - 1)**2 + 1 # 函数 y = (x-1)^2 + 1
# 计算 x = 6 时的 y 值
cur_x = 6
cur_y = (cur_x - 1)**2 + 1
eta = 0.05
iter = 1000
all_x = []# 记录迭代过程中的 x 值
all_y = []# 记录迭代过程中的 y 值
for i in range(iter):
# 记录迭代过程
all_x.append(cur_x)
all_y.append(cur_y)
# 计算导数
dy = 2*cur_x - 2
# 更新 x 和 y
cur_x = cur_x - eta*dy
cur_y = (cur_x - 1)**2 + 1
# 绘图
plt.figure(figsize=(10, 6)) # 设置图形大小
plt.plot(x, y, label=r'$y = (x-1)^2 + 1$', color='blue') # 绘制函数曲线
plt.title('Plot of $y = (x-1)^2 + 1$') # 图形标题
plt.xlabel('x') # x 轴标签
plt.ylabel('y') # y 轴标签
plt.axhline(0, color='black', linewidth=0.5, ls='--') # 添加 x 轴
plt.axvline(0, color='black', linewidth=0.5, ls='--') # 添加 y 轴
plt.grid(True) # 添加网格
plt.legend() # 添加图例
plt.scatter(np.array(all_x), np.array(all_y), color='red')# 绘制迭代过程
plt.show() # 显示图形