Learn practical skills, build real-world projects, and advance your career

线性模型和梯度下降

这是一个非常简单的模型,线性回归,同时也会学习一个优化算法-梯度下降法,对这个模型进行优化。线性回归是监督学习里面一个非常简单的模型,同时梯度下降也是深度学习中应用最广的优化算法,我们将从这里开始我们的深度学习之旅。

一元线性回归

一元线性模型非常简单,假设我们有变量xix_i和目标yiy_i,每个ii对应于一个数据点,希望建立一个模型 y^i=wxi+b\hat{y}_i = w x_i + b

y^i\hat{y}_i是我们预测的结果,希望通过y^i\hat{y}_i来拟合目标yiy_i, 通俗来讲就是找到这个函数拟合yiy_i使得误差最小,即最小化1ni=1n(y^iyi)2\frac{1}{n}\sum_{i=1}^n(\hat{y}_i - y_i)^2

那么如何最小化这个误差呢
这里需要用到梯度下降,这是我们接触到的第一个优化算法,非常简单,但是却非常强大,在深度学习中被大量使用,所以让我们从简单的例子出发了解梯度下降的原理。

梯度下降法

在梯度下降法中,首先要明确梯度的概念,随后我们再了解如何使用梯度进行下降。

梯度

梯度在数学上就是导数,如果是一个多元函数,那么梯度就是偏导数。比如一个函数f(x,y)f(x,y),那么ff的梯度就是(fx,fy)(\frac{\partial f}{\partial x},\frac{\partial f}{\partial y})

可以称为gradf(x,y)f(x,y)或者f(x,y)\nabla f(x, y)。具体一点(x0,y0)(x_0, y_0)的梯度就是f(x,y)\nabla f(x, y)

下面这个图片是f(x)=x2f(x) = x^2这个函数在x=1处的梯度
alt

梯度有什么意义呢?从几何意义上来讲,一个点的梯度值是这个函数变化最快的地方,具体来说,对于函数f(x,y)f(x,y),在点(x0,y0)(x_0,y_0)处,沿着梯度f(x,y)\nabla f(x, y)的方向,函数增加最快,也就是说沿着梯度的方向,我们能够更快的找到函数的极大值点,或者反过来沿着梯度的反方向,能够更快的找到函数的最小值点。

梯度下降法

有了对梯度的理解,我们就能了解梯度下降发的原理了。上面我们需要最小化这个误差,也就是需要找到这个误差的最小值点,那么沿着梯度的反方向我们就能够找到这个最小值点。

我们可以来看一个直观的解释。比如我们在一座大山上的某处位置,由于我们不知道怎么下山,于是决定走一步算一步,也就是在每走到一个位置的时候,求解当前位置的梯度,沿着梯度的负方向,也就是当前最陡峭的位置向下走一步,然后继续求解当前位置梯度,向这一步所在位置沿着最陡峭最易下山的位置走一步。这样一步步的走下去,一直走到觉得我们已经到了山脚。当然这样走下去,有可能我们不能走到山脚,而是到了某一个局部的山峰低处。

类比我们的问题,就是沿着梯度的反方向,我们不断改变wwbb的值,最终找到一组最好的wwbb,使得误差最小。

在更新的时候,我们需要决定每次更新的幅度,比如在下山的例子中,我们需要每次往下走的那一步的长度,这个长度称为学习率,用 η\eta 表示,这个学习率非常重要,不同的学习率都会导致不同的结果,学习率太小会导致下降非常缓慢,学习率太大又会导致跳动非常明显,可以看看下面的例子
alt
可以看到上面的学习率较为合适,而下面的学习率太大,就会导致不断跳动

最后我们的更新公式就是alt
通过不断地迭代更新,最终我们能够找到一组最优的wwbb,这就是梯度下降法的原理。

最后可以通过这张图形象地说明一下这个方法alt

import torch
import numpy as np
from torch.autograd import Variable
torch.manual_seed(2018)
<torch._C.Generator at 0x7f603c0619b0>
# 读入数据
x_train = np.array([[3.3], [4.4], [5.5], [6.71], [6.93], [4.168],
                    [9.779], [6.182], [7.59], [2.167], [7.042],
                    [10.791], [5.313], [7.997], [3.1]], dtype=np.float32)

y_train = np.array([[1.7], [2.76], [2.09], [3.19], [1.694], [1.573],
                    [3.366], [2.596], [2.53], [1.221], [2.827],
                    [3.465], [1.65], [2.904], [1.3]], dtype=np.float32)
# 画出图像
import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(x_train, y_train, 'bo')
[<matplotlib.lines.Line2D at 0x7f5fe483fd30>]
Notebook Image
# 转换成Tensor
x_train = torch.from_numpy(x_train)
y_train = torch.from_numpy(y_train)

# 定义参数w和b
# 随机初始化
w = Variable(torch.randn(1), requires_grad=True) 
# 初始化0
b = Variable(torch.zeros(1), requires_grad=True)