人工智能---梯度下降的原理和手写实现

系列文章目录

人工智能–机器学习线性回归数学原理及实现



前言

      其实在之前机器学习的章节中我们已经提到了梯度下降的概念,并且用梯度下降解决了实际的最小二乘法求解问题,来完成线性回归的一个例子,大家知道了梯度下降法能让最小二乘法的结果每次都趋向更小,但大家可能还是不太清楚他的本质原理。这一章中我就会给大家真真正正的讲解梯度下降的算法。


一、什么是梯度下降?

      梯度下降其实是梯度问题里的一种,只是我们用的比较多,但根据实际情况,我们将梯度问题分为:梯度下降和梯度上升,分别用来求解最小值和最大值问题。而梯度的概念其实很简单,当一个式子的向量由该式子的全部变量的偏导数组成时,这个向量被称为梯度(gradient)。我们用式子来表达可能会更加形象:
假设我们有对象表达式:
f ( x 0 , x 1 ) = x 0 2 + x 1 2 f(x_{0},x_{1})=x_{0}^2+x_1^2 f(x0,x1)=x02+x12
则他的梯度为:
v e c t o r → = ( ∂ f ∂ x 0 , ∂ f ∂ x 1 ) \overrightarrow{vector} = ( \frac{\partial f}{\partial x_{0}}, \frac{\partial f}{\partial x_{1}} ) vector =(x0f,x1f)

二、为什么梯度的方向是下降最快的方向

1.偏导数的意义

      那我们首先要从梯度的组成入手,可以看到梯度是由两个偏导数 ( ∂ f ∂ x 0 , ∂ f ∂ x 1 ) (\frac{\partial f}{\partial x_0},\frac{\partial f}{\partial x_1}) (x0f,x1f)组成

而其中:
f x ( x 0 , y 0 ) f_{x}(x_0,y_0) fx(x0,y0)代表曲面被平面 y = y 0 y = y_0 y=y0所截后的曲面在点M出的切线对 x x x轴的斜率,
f y ( x 0 , y 0 ) f_{y}(x_0,y_0) fy(x0,y0)代表曲面被平面 x = x 0 x = x_0 x=x0所截后的曲面在点M出的切线对 y y y轴的斜率,

于是我们可以看到由于偏导数的局限性,我们很难进行任意方向的变化率计算,于是我们引入了方向导数的概念。

2.方向导数

因为我们已经有了两个方向的偏导数 f x ( x 0 , y 0 ) , f y ( x 0 , y 0 ) f_x(x_0,y_0),f_y(x_0,y_0) fx(x0,y0),fy(x0,y0),那类似与向量平面可以由两个向量表达一样,我们也可以通过这俩个偏导数来表示各个方向。
于是我们提出:
u ⃗ = cos ⁡ θ i + sin ⁡ θ j \vec u = \cos\theta{i}+\sin\theta{j} u =cosθi+sinθj
当然由于他是针对二元函数 f ( x , y ) f(x,y) f(x,y)的,所以这个方向还需要一个前置条件:
lim ⁡ t → 0 f ( x 0 + t cos ⁡ θ , y 0 + t sin ⁡ θ ) t \lim_{t\to0} \frac{f(x_0+t\cos\theta,y_0+t\sin\theta)} {t} t0limtf(x0+tcosθ,y0+tsinθ)这条表达式的极限值如果存在,则可以说我们的方向向量成立,我们将其记为 D u f ( x , y ) D_uf(x,y) Duf(x,y)
由于我们已知 D u f ( x , y ) = f x ( x , y ) cos ⁡ θ + f y ( x , y ) sin ⁡ θ D_uf(x,y)=f_x(x,y)\cos\theta+f_y(x,y)\sin\theta Duf(x,y)=fx(x,y)cosθ+fy(x,y)sinθ成立。
设:
P = ( f x ( x , y ) , f y ( x , y ) ) P = (f_x(x,y),f_y(x,y)) P=(fx(x,y),fy(x,y))
W = ( cos ⁡ θ , sin ⁡ θ ) W = (\cos\theta,\sin\theta) W=(cosθ,sinθ)
则:
D u f ( x , y ) = P ⋅ W = ∣ P ∣ ⋅ ∣ W ∣ cos ⁡ α D_uf(x,y)=P·W =\left\vert P\right\vert·\left\vert W\right\vert \cos\alpha Duf(x,y)=PW=PWcosα
这样原理一下子就清晰了,想要 D u f ( x , y ) D_uf(x,y) Duf(x,y)最大也就是 cos ⁡ α \cos\alpha cosα取1,也就是 W W W P P P平行,其中P是我们的梯度,而W是我们在尝试的方向,所以当然是让W和我们的P相同时 D u f ( x , y ) D_uf(x,y) Duf(x,y)最大,也就是这个方向幅度最大。

3.实验证明

首先画出我们的函数图像

X0 = np.arange(-6, 6, 0.25)
X1 = np.arange(-6, 6, 0.25)
X0, X1 = np.meshgrid(X0, X1)

Z = np.power(X0,2)+np.power(X1,2)

在这里插入图片描述
可以添加一点投影,更加直观的从每个维度观察变化趋势。

在这里插入图片描述
然后求我们的梯度

先做一个求导的函数

def _numerical_gradient_no_batch(f, x):
    h = 1e-4  # 0.0001
    grad = np.zeros_like(x)

    for idx in range(x.size):
        tmp_val = x[idx]
        x[idx] = float(tmp_val) + h
        fxh1 = f(x)  # f(x+h)

        x[idx] = tmp_val - h
        fxh2 = f(x)  # f(x-h)
        grad[idx] = (fxh1 - fxh2) / (2 * h)

        x[idx] = tmp_val  # 还原值

    return grad

再生成我们的函数 f ( x 0 , x 1 ) = x 0 2 + x 1 2 f(x_0,x_1)=x_0^2+x_1^2 f(x0,x1)=x02+x12

def function_2(x):
    if x.ndim == 1:
        return np.sum(x ** 2)
    else:
        return np.sum(x ** 2, axis=1)

最后进行求导

def numerical_gradient(f, X):
    if X.ndim == 1:
        return _numerical_gradient_no_batch(f, X)
    else:
        grad = np.zeros_like(X)

        for idx, x in enumerate(X):
            grad[idx] = _numerical_gradient_no_batch(f, x)

        return grad
grad = numerical_gradient(function_2, np.array([X, Y]))

然后向量图

plt.quiver(X, Y, -grad[0], -grad[1], angles="xy", color="#666666")

得出结果

我们可以看到对应上面我们 f ( x 0 , x 1 ) f(x_0,x_1) f(x0,x1)的z方向投影图,每个方向的梯度都在向着最低点汇聚。


总结

      所以综上所述,梯度下降法在求解很多函数上都有起效,也就是我们前面在解决最小二乘法的时候选择他的原因,同时,梯度的求解方法在后面神经网络的学习中是非常重要的,可以说是一个核心思想。

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Foxerity

看心情就好啦

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

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

打赏作者

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

抵扣说明:

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

余额充值