问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

方向导数和梯度

创作时间:
作者:
@小白创作中心

方向导数和梯度

引用
CSDN
1.
https://m.blog.csdn.net/m0_56878426/article/details/140106305

方向导数和梯度是微积分中的重要概念,也是机器学习中梯度下降算法的基础。本文将从导数的回忆开始,逐步深入到偏导数、方向导数和梯度的定义和几何意义,并最终介绍梯度下降算法的原理和实现。

1 导数的回忆

导数的几何意义如图所示:

当P0点不断接近P时,导数如下定义:

$$
f'(x_0) = \lim_{\Delta x \to 0} \frac{\Delta y}{\Delta x} = \lim_{\Delta x \to 0} \frac{f(x_0 + \Delta x) - f(x_0)}{\Delta x}
$$

2 偏导数及其向量形式

偏导数的几何意义

对x的偏导数定义如下:

$$
\frac{\partial f}{\partial x}(x_0, y_0) = \lim_{\Delta x \to 0} \frac{f(x_0 + \Delta x, y_0) - f(x_0, y_0)}{\Delta x}
$$

如图所示,$M_0(x_0, y_0, f(x_0, y_0))$是曲线$z=f(x,y)$的一点,过$M_0$作平面$y=y_0$截此曲面得一曲线,此曲线的方程为:$z=f(x,y_0)$,则上述对x的偏导数就是在点$M_0$处的切线$M_0T_x$对x轴的斜率。对y的偏导数的几何意义同理。

偏导数的向量形式

为了等一下方便理解方向导数,将上述的偏导数表示成向量形式。

设$\vec{a}=\begin{bmatrix}x_0\ y_0\end{bmatrix}$,则对x的偏导数为:

$$
\frac{\partial f}{\partial x}(\vec{a})=\lim_{h\to 0} \frac{f(\vec{a}+h\hat{i})-f(\vec{a})}{h}
$$

其中$\hat{i}=\begin{bmatrix}1\ 0\end{bmatrix}$

3 方向导数

向量形式

从偏导数的向量形式可知:当$\hat{i}$方向改变时,就产生了方向导数。

方向导数的定义如下:

$$
\nabla_{\vec{v}}f(\vec{a})=\frac{\partial f}{\partial \vec{v}}(\vec{a})=\lim_{h\to 0} \frac{f(\vec{a}+h\vec{v})-f(\vec{a})}{h}
$$

这种定义有一种问题,假设$\vec{v}$变为原来的两倍,但分母不变,则实际上方向导数也会变成2倍。

如果要把方向导数表示成该方向的斜率,则应该用如下定义:

$$
\nabla_{\vec{v}}f(\vec{a})=\frac{\partial f}{\partial \vec{v}}(\vec{a})=\lim_{h\to 0} \frac{f(\vec{a}+h\vec{v})-f(\vec{a})}{h|\vec{v}|}
$$

在该定义下,表示的是函数在某点沿着$\vec{a}$方向上的导数,即斜率

几何意义

方向导数的非向量形式如下:

设$e_l=(cos\alpha,cos\beta)$是与l同方向的单位向量,设射线l上P的坐标为$P=(x_0+tcos\alpha,y_0+tcos\beta)$,此时如下图所示:

此时函数增量与距离$|PP_0|=t$的比值为:

$$
\frac{f(x_0+tcos\alpha,y_0+tcos\beta)-f(x_0,y_0)}{t}
$$

当P沿着l趋于$P_0$时,若极限存在,则称为函数$f(x,y)$在点$P_0$沿方向l的方向导数,即上面向量形式的第二种定义(只不过这里用了非向量形式),如下:

$$
\frac{\partial f}{\partial l}\vert_{(x_0,y_0)}=\lim_{t\to 0^{+}}\frac{f(x_0+tcos\alpha,y_0+tcos\beta)-f(x_0,y_0)}{t}
$$

其几何意义如下图所示:如果要求A点在紫色向量方向上的斜率(红色线圈出来的),则可用方向导数

方向导数和偏导的关系

定理: 如果函数$f(x,y)$在点$P_0(x_0,y_0)$可微分,那么函数在该点沿任一方向l的方向导数存在,且有

$$
\frac{\partial f}{\partial l}\vert_{(x_0,y_0)}=f_{x}(x_0,y_0)cos\alpha+f_{y}cos\beta
$$

其中$cos\alpha$和$cos\beta$是方向l的方向余弦

证明:由函数$f(x,y)$在点$P_0(x_0,y_0)$可微分可得:

$$
f(x_0+\Delta x,y_0+\Delta y)-f(x_0,y_0)=f_{x}(x_0,y_0)\Delta x+f_{y}\Delta y+o(\sqrt{\Delta x^{2}+\Delta y^{2} })
$$

由上述可知:$\Delta x=tcos\alpha,\Delta y=tcos\beta$,则有:$\sqrt{\Delta x^{2}+\Delta y^{2} }=t$

从而有:

$$
\begin {aligned}
\lim_{t\to 0^{+}}\frac{f(x_0+tcos\alpha,y_0+tcos\beta)-f(x_0,y_0)}{t}& =\lim_{t\to 0^{+}}\frac{f_{x}(x_0,y_0)tcos\alpha+f_{y}tcos\beta+o(t)}{t} \
&=f_{x}(x_0,y_0)cos\alpha+f_{y}cos\beta
\end {aligned}
$$

相当于方向导数是偏导数的线性组合

4 梯度

在二元函数情况下,设函数$f(x,y)$在平面区域D内具有一阶连续偏导数,则对于每一点$P_0(x_0,y_0)\in D$,都存在一个梯度,记作$grad f(x_0,y_0)$或$\nabla f(x_0,y_0)$:

$$
grad f(x_0,y_0) = \nabla f(x_0,y_0) = \begin{bmatrix}\frac{\partial f}{\partial x} \ \ \frac{\partial f}{\partial y}\end{bmatrix}
$$

因此,假设函数$f(x,y)$在点$P_0(x_0,y_0)$可微分,$e_l=(cos\alpha,cos\beta)$是与方向l同向的方向向量,则方向导数和梯度的关系是:

$$
\begin {aligned}
\frac{\partial f}{\partial l}\vert_{(x_0,y_0)}& = f_{x}(x_0,y_0)cos\alpha+f_{y}cos\beta \
&=\nabla f(x_0,y_0) \ \cdot \ e_{l} \
&=|\nabla f(x_0,y_0)| \ |e_{l}| \ cos\theta \
&=|\nabla f(x_0,y_0)|\ cos\theta
\end {aligned}
$$

其中,$\theta$是向量$\nabla f(x_0,y_0)$与向量$e_l$所成夹角,因此可以得出下述结论:

  • $\theta=0$,向量$\nabla f(x_0,y_0)$与向量$e_l$方向相同,此时方向导数最大,函数$f(x,y)$增长最快
  • $\theta=\pi$,向量$\nabla f(x_0,y_0)$与向量$e_l$方向相反,此时方向导数最小,函数$f(x,y)$减少最快
  • $\theta=\frac{\pi}{2}$,向量$\nabla f(x_0,y_0)$与向量$e_l$方向正交,函数$f(x,y)$变化率为0
  • 综上,沿着梯度方向函数增长最快

5 梯度下降算法

梯度下降法(Gradient Descent)是一种用于寻找函数极小值的一阶迭代优化算法,又称为最速下降(Steepest Descent)。以下是梯度下降的基本公式:

$$
\theta \leftarrow \theta -\eta\frac{\partial L(\theta)}{\partial \theta }
$$

可以看出:

  • $L(\theta)$是关于$\theta$的损失函数
  • $\eta$是学习率,称为梯度下降的步长,
  • 梯度下降法是让方向导数最小时做迭代

举一个例子:设$L(\theta)=\theta^{2}$,则梯度$\nabla L(\theta)=\frac{\partial L(\theta)}{\partial \theta }=2\theta$;设学习率为$\eta=0.2$;设初始值为$(\theta_0, L(\theta_0))=(10, 100)$,此时梯度为:$\nabla L(\theta_0)=2\theta_0=20$。

  • 更新$\theta$:$\theta_1 \leftarrow \theta_0 -\eta\frac{\partial L(\theta_0)}{\partial \theta_0} = 10-0.2×20=6$
  • 重复上述步骤,直至$\theta$收敛

代码如下:

import numpy as np
import matplotlib.pyplot as plt

# 定义损失函数 y = x^2
def f(x):
    return x**2

# 梯度下降函数
def gradient_descent(x, eta):
    # 计算斜率
    slope = 2 * x
    # 更新 x 的值
    x_out = x - eta * slope
    return x_out, slope

# 主程序
def main():
    # 初始化参数
    x_data = np.linspace(-10, 10, 1000)  # x 范围
    LRate = 0.2  # 学习率
    slope_thresh = 0.0001  # 斜率阈值

    # 绘制损失函数图像
    plt.plot(x_data, f(x_data), 'c', linewidth=2)
    plt.title('y = x^2 (learning rate = 0.2)')
    plt.xlabel('x')
    plt.ylabel('y = x^2')
    plt.grid(True)

    # 初始点设置为 (10, f(10))
    x = 10
    y = f(10)
    plt.plot(x, y, 'r*')

    # 开始梯度下降迭代
    slope = float('inf')  # 初始斜率设置为无穷大
    while abs(slope) > slope_thresh:
        x_new, slope = gradient_descent(x, LRate)
        y_new = f(x_new)

        # 绘制当前点到更新后点的连线
        plt.plot([x, x_new], [y, y_new], 'k--', linewidth=1)

        # 绘制点
        plt.plot(x_new, y_new, 'r*')
        plt.legend(['y = x^2', 'Gradient descent path'])
        plt.draw()
        plt.pause(0.2)  # 暂停一小段时间,使得动态图像可见

        x = x_new
        y = y_new

    plt.show()

# 当这个 .py 文件被直接运行时(作为主程序),执行 main() 函数;
# 当这个 .py 文件被导入到其他模块中时,不执行 main() 函数,因为 __name__ 的值不是 '__main__'。
if __name__ == '__main__':
    main()

应尽可能选择适中的学习率,过大会震荡,过小迭代次数会过多,如下所示,学习率为0.2更好。

当学习率$\eta=0.2$时,图像如下:

当学习率$\eta=0.9$时,图像如下:

当学习率$\eta=0.01$时,图像如下:

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号