系列文章目录
人工智能–机器学习线性回归数学原理及实现
文章目录
- 系列文章目录
- 前言
- 一、什么是梯度下降?
- 二、为什么梯度的方向是下降最快的方向
- 1.偏导数的意义
- 2.方向导数
- 3.实验证明
- 总结
前言
其实在之前机器学习的章节中我们已经提到了梯度下降的概念,并且用梯度下降解决了实际的最小二乘法求解问题,来完成线性回归的一个例子,大家知道了梯度下降法能让最小二乘法的结果每次都趋向更小,但大家可能还是不太清楚他的本质原理。这一章中我就会给大家真真正正的讲解梯度下降的算法。
一、什么是梯度下降?
梯度下降其实是梯度问题里的一种,只是我们用的比较多,但根据实际情况,我们将梯度问题分为:梯度下降和梯度上升,分别用来求解最小值和最大值问题。而梯度的概念其实很简单,当一个式子的向量由该式子的全部变量的偏导数组成时,这个向量被称为梯度(gradient)。我们用式子来表达可能会更加形象:
假设我们有对象表达式:
则他的梯度为:
二、为什么梯度的方向是下降最快的方向
1.偏导数的意义
组成
而其中:
代表曲面被平面所截后的曲面在点M出的切线对轴的斜率,
代表曲面被平面所截后的曲面在点M出的切线对轴的斜率,
于是我们可以看到由于偏导数的局限性,我们很难进行任意方向的变化率计算,于是我们引入了方向导数的概念。
2.方向导数
因为我们已经有了两个方向的偏导数,那类似与向量平面可以由两个向量表达一样,我们也可以通过这俩个偏导数来表示各个方向。
于是我们提出:
当然由于他是针对二元函数的,所以这个方向还需要一个前置条件:
这条表达式的极限值如果存在,则可以说我们的方向向量成立,我们将其记为
由于我们已知成立。
设:
则:
这样原理一下子就清晰了,想要最大也就是取1,也就是和平行,其中P是我们的梯度,而W是我们在尝试的方向,所以当然是让W和我们的P相同时最大,也就是这个方向幅度最大。
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
再生成我们的函数
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")
得出结果
我们可以看到对应上面我们的z方向投影图,每个方向的梯度都在向着最低点汇聚。
总结
所以综上所述,梯度下降法在求解很多函数上都有起效,也就是我们前面在解决最小二乘法的时候选择他的原因,同时,梯度的求解方法在后面神经网络的学习中是非常重要的,可以说是一个核心思想。