第2章 回归问题
有些人担心人工智能会让人类觉得自卑,但是实际上,即使是看到一朵花,我们也应该或多或少感到一些自愧不如。−艾伦·凯
2.1 神经元模型
成年人大脑中包含了约 1000 亿个神经元,每个神经元通过树突获取输入信号,通过轴突传递输出信号,神经元之间相互连接构成了巨大的神经网络,从而形成了人脑的感知和意识基础,图 2.1 是一种典型的生物神经元结构。1943 年,心理学家沃伦·麦卡洛克(Warren McCulloch)和数理逻辑学家沃尔特·皮茨(Walter Pitts)通过对生物神经元的研究,提出了模拟生物神经元机制的人工神经网络的数学模型 (McCulloch & Pitts, 1943),这一成果被美国神经学家弗兰克·罗森布拉特(Frank Rosenblatt)进一步发展成感知机(Perceptron)模型,这也是现代深度学习的基石。
我们将从生物神经元的结构出发,重温科学先驱们的探索之路,逐步揭开自动学习机器的神秘面纱。
首先,我们把生物神经元(Neuron)的模型抽象为如图 2.2(a)所示的数学结构:神经元输入向量𝒙 = [𝑥1, 𝑥2, 𝑥3, … , 𝑥𝑛]T,经过函数映射:𝑓𝜃: 𝒙 → 𝑦后得到输出𝑦,其中𝜃为函数𝑓自身的参数。考虑一种简化的情况,即线性变换:𝑓(𝒙) = 𝒘T𝒙 + 𝑏,展开为标量形式:
𝑓(𝒙) = 𝑤1𝑥1 + 𝑤2𝑥2 + 𝑤3𝑥3 + ⋯ + 𝑤𝑛𝑥𝑛 + 𝑏
上述计算逻辑可以通过图 2.2(b)直观地展现
参数𝜃 ∶= {𝑤1, 𝑤2, 𝑤3, . . . , 𝑤𝑛,𝑏}确定了神经元的状态,通过固定𝜃参数即可确定此神经元的处理逻辑。当神经元输入节点数𝑛 = 1(单输入)时,神经元数学模型可进一步简化为:𝑦 = 𝑤𝑥 + 𝑏
此时我们可以绘制出神经元的输出𝑦和输入𝑥的变化趋势,如图 2.3 所示,随着输入信号𝑥的增加,输出电平𝑦也随之线性增加,其中𝑤参数可以理解为直线的斜率(Slope),b 参数为直线的偏置(Bias)。
对于某个神经元来说,𝑥和𝑦的映射关系
f
w
,
b
f_{w,b}
fw,b是未知但确定的。两点即可确定一条直线,为了估计𝑤和𝑏的值,我们只需从图 2.3 中直线上采样任意 2 个数据点:
(
x
(
1
)
,
y
(
1
)
)
,
(
x
(
2
)
,
y
(
2
)
)
\left(x^{(1)}, y^{(1)}\right),\left(x^{(2)}, y^{(2)}\right)
(x(1),y(1)),(x(2),y(2))即可,其中上标表示数据点编号:
y
(
1
)
=
w
x
(
1
)
+
b
y
(
2
)
=
w
x
(
2
)
+
b
\begin{array}{l} y^{(1)}=w x^{(1)}+b \\ y^{(2)}=w x^{(2)}+b \end{array}
y(1)=wx(1)+by(2)=wx(2)+b
当
(
x
(
1
)
,
y
(
1
)
)
≠
(
x
(
2
)
,
y
(
2
)
)
\left(x^{(1)}, y^{(1)}\right) \neq\left(x^{(2)}, y^{(2)}\right)
(x(1),y(1))=(x(2),y(2))时,通过求解上式便可计算出𝑤和𝑏的值。考虑某个具体的例子:
x
(
1
)
=
1
,
y
(
1
)
=
1.567
,
x
(
2
)
=
2
,
y
(
2
)
=
3.043
x^{(1)}=1, y^{(1)}=1.567, x^{(2)}=2, y^{(2)}=3.043
x(1)=1,y(1)=1.567,x(2)=2,y(2)=3.043, 代入上式中可得:
1.567
=
w
⋅
1
+
b
3.043
=
w
⋅
2
+
b
\begin{array}{l} 1.567=w \cdot 1+b \\ 3.043=w \cdot 2+b \end{array}
1.567=w⋅1+b3.043=w⋅2+b
这就是我们初中时代学习过的二元一次方程组,通过消元法可以轻松计算出𝑤和𝑏的解析解:𝑤 = 1. 477, 𝑏 = 0.089 。
可以看到,只需要观测两个不同数据点,就可完美求解单输入线性神经元模型的参数,对于𝑁输入的现象神经元模型,只需要采样𝑁 + 1组不同数据点即可,似乎线性神经元模型可以得到完美解决。那么上述方法存在什么问题呢?考虑对于任何采样点,都有可能存在观测误差,我们假设观测误差变量
ϵ
\epsilon
ϵ属于均值为𝜇,方差为
σ
2
\sigma^{2}
σ2的正态分布(NormalDistribution,或高斯分布,Gaussian Distribution):
N
(
μ
,
σ
2
)
\mathcal{N}\left(\mu, \sigma^{2}\right)
N(μ,σ2),则采样到的样本符合:
y
=
w
x
+
b
+
ϵ
,
ϵ
∼
N
(
μ
,
σ
2
)
y=w x+b+\epsilon, \epsilon \sim \mathcal{N}\left(\mu, \sigma^{2}\right)
y=wx+b+ϵ,ϵ∼N(μ,σ2)
一旦引入观测误差后,即使简单如线性模型,如果仅采样两个数据点,可能会带来较大估计偏差。如图 2.4 所示,图中的数据点均带有观测误差,如果基于蓝色矩形块的两个数据点进行估计,则计算出的蓝色虚线与真实橙色直线存在较大偏差。为了减少观测误差引入的估计偏差,可以通过采样多组数据样本集合𝔻 =
{
(
x
(
1
)
,
y
(
1
)
)
,
(
x
(
2
)
,
y
(
2
)
)
,
…
,
(
x
(
n
)
,
y
(
n
)
)
}
\left\{\left(x^{(1)}, y^{(1)}\right),\left(x^{(2)}, y^{(2)}\right), \ldots,\left(x^{(n)}, y^{(n)}\right)\right\}
{(x(1),y(1)),(x(2),y(2)),…,(x(n),y(n))},然后找出一条“最好”的直线,使得它尽可能地让所有采样点到该直线的误差(Error,或损失 Loss)之和最小。
也就是说,由于观测误差
ϵ
\epsilon
ϵ的存在,当我们采集了多个数据点𝔻时,可能不存在一条直线完美的穿过所有采样点。退而求其次,我们希望能找到一条比较“好”的位于采样点中间的直线。那么怎么衡量“好”与“不好”呢?一个很自然的想法就是,求出当前模型的所有采样点上的预测值
w
x
(
i
)
+
b
w x^{(i)}+b
wx(i)+b与真实值
y
(
i
)
y^{(i)}
y(i)之间的差的平方和作为总误差ℒ:
L
=
1
n
∑
i
=
1
n
(
w
x
(
i
)
+
b
−
y
(
i
)
)
2
\mathcal{L}=\frac{1}{n} \sum_{i=1}^{n}\left(w x^{(i)}+b-y^{(i)}\right)^{2}
L=n1i=1∑n(wx(i)+b−y(i))2
然后搜索一组参数
w
∗
,
b
∗
w^{*}, b^{*}
w∗,b∗使得ℒ最小,对应的直线就是我们要寻找的最优直线:
w
∗
,
b
∗
=
argmin
w
,
b
1
n
∑
i
=
1
n
(
w
x
(
i
)
+
b
−
y
(
i
)
)
2
w^{*}, b^{*}=\underset{w, b}{\operatorname{argmin}} \frac{1}{n} \sum_{i=1}^{n}\left(w x^{(i)}+b-y^{(i)}\right)^{2}
w∗,b∗=w,bargminn1i=1∑n(wx(i)+b−y(i))2
其中𝑛表示采样点的个数。这种误差计算方法称为均方误差(Mean Squared Error,简称
MSE)。
2.2 优化方法
现在来小结一下上述方案:我们需要找出最优参数(Optimal Parameter) w ∗ , b ∗ w^{*}, b^{*} w∗,b∗,使得输入和输出满足线性关系 y ( i ) = w x ( i ) + b , i ∈ [ 1 , n ] y^{(i)}=w x^{(i)}+b, i \in[1, n] y(i)=wx(i)+b,i∈[1,n]。但是由于观测误差 ϵ \epsilon ϵ的存在,需要通过采样足够多组的数据样本组成的数据集(Dataset):𝔻 ={(𝑥(1),𝑦(1)), (𝑥(2),𝑦(2)),… , (𝑥(𝑛), 𝑦(𝑛))},找到一组最优的参数 w ∗ , b ∗ w^{*}, b^{*} w∗,b∗使得均方差ℒ = 1 n ∑ i = 1 n ( w x ( i ) + b − y ( i ) ) 2 \frac{1}{n} \sum_{i=1}^{n}\left(w x^{(i)}+b-y^{(i)}\right)^{2} n1∑i=1n(wx(i)+b−y(i))2 最小。
对于单输入的神经元模型,只需要两个样本,能通过消元法求出方程组的精确解,这种通过严格的公式推导出的精确解称为解析解(Closed-form Solution)。
但是对于多个数据点(𝑛 ≫ 2)的情况,这时很有可能不存在解析解,我们只能借助数值方法去优化(Optimize)出一个近似的数值解(Numerical Solution)。为什么叫作优化?这是因为计算机的计算速度非常快,我们可以借助强大的计算能力去多次“搜索”和“试错”,从而一步步降低误差ℒ。
最简单的优化方法就是暴力搜索或随机试验,比如要找出最合适的 w ∗ , b ∗ w^{*}, b^{*} w∗,b∗,我们就可以从(部分)实数空间中随机采样任意的𝑤和𝑏,并计算出对应模型的误差值 L \mathcal{L} L,然后从测试过的{ L \mathcal{L} L}中挑出最好的 L ∗ \mathcal{L}^{*} L∗,它所对应的𝑤和𝑏就可以作为我们要找的最优 w ∗ , b ∗ w^{*}, b^{*} w∗,b∗。
这种算法固然简单直接,但是面对大规模、高维度数据的优化问题时计算效率极低,基本不可行。
梯度下降算法(Gradient Descent)是神经网络训练中最常用的优化算法,配合强大的图形处理芯片 GPU(Graphics Processing Unit)的并行加速能力,非常适合优化海量数据的神经网络模型,自然也适合优化我们这里的神经元线性模型。这里先简单地应用梯度下降算法,用于解决神经元模型预测的问题。由于梯度下降算法是深度学习的核心算法,我们将在第 7 章非常详尽地推导梯度下降算法在神经网络中的应用,这里先给读者第一印象。
我们在高中时代学过导数(Derivative)的概念,如果要求解一个函数的极大、极小值,可以简单地令导数函数为 0,求出对应的自变量点(称为驻点),再检验驻点类型即可。以函数𝑓(𝑥) =
x
(
2
)
x^{(2)}
x(2)∙ 𝑠𝑖𝑛 (𝑥)为例,我们绘制出函数及其导数在𝑥 ∈ [−1 ,1 ]区间曲线,其中蓝色实线为𝑓(𝑥),黄色虚线为
d
f
(
x
)
d
x
\frac{\mathrm{d} f(x)}{\mathrm{d} x}
dxdf(x),如图 2.5 所示。可以看出,函数导数(虚线)为 0 的点即为𝑓(𝑥)的驻点,函数的极大值和极小值点均出现在驻点中。
函数的梯度(Gradient)定义为函数对各个自变量的偏导数(Partial Derivative)组成的向量。考虑 3 维函数𝑧 = 𝑓(𝑥, 𝑦),函数对自变量𝑥的偏导数记为 ∂ z ∂ x \frac{\partial z}{\partial x} ∂x∂z,函数对自变量y的偏导数记为 ∂ z ∂ y \frac{\partial z}{\partial y} ∂y∂z,则梯度∇𝑓为向量 ( ∂ z ∂ x , ∂ z ∂ y ) \left(\frac{\partial z}{\partial x}, \frac{\partial z}{\partial y}\right) (∂x∂z,∂y∂z)。我们通过一个具体的函数来感受梯度的性质,
如图 2.6所示,
f
(
x
,
y
)
=
−
(
cos
2
x
+
cos
2
y
)
2
f(x, y)=-\left(\cos ^{2} x+\cos ^{2} y\right)^{2}
f(x,y)=−(cos2x+cos2y)2,图中𝑥𝑦平面的红色箭头的长度表示梯度向量的模,箭头的方向表示梯度向量的方向。可以看到,箭头的方向总是指向当前位置函数值增速最大的方向,函数曲面越陡峭,箭头的长度也就越长,梯度的模也越大。
通过上面的例子,我们能直观地感受到,函数在各处的梯度方向∇𝑓总是指向函数值增大的方向,那么梯度的反方向−∇𝑓应指向函数值减少的方向。利用这一性质,我们只需要按照
x
′
=
x
−
η
⋅
∇
f
x^{\prime}=x-\eta \cdot \nabla f
x′=x−η⋅∇f
来迭代更新𝒙′,就能获得越来越小的函数值,其中𝜂用来缩放梯度向量,一般设置为某较小的值,如 0.01,0.001 等。特别地,对于一维函数,上述向量形式可以退化成标量形式:
x
′
=
x
−
η
⋅
d
y
d
x
x^{\prime}=x-\eta \cdot \frac{\mathrm{d} y}{\mathrm{d} x}
x′=x−η⋅dxdy
通过上式迭代更新𝑥′若干次,这样得到的𝑥′处的函数值𝑦′,总是更有可能比在𝑥处的函数值𝑦小。
通过上面公式优化参数的方法称为梯度下降算法,它通过循环计算函数的梯度∇𝑓并更新待优化参数𝜃,从而得到函数𝑓获得极小值时参数𝜃的最优数值解。需要注意的是,在深度学习中,一般𝒙表示模型输入,模型的待优化参数一般用𝜃、𝑤、𝑏等符号表示。
现在我们将应用速学的梯度下降算法来求解
w
∗
,
b
∗
w^{*}, b^{*}
w∗,b∗参数。这里要最小化的是均方差误差函数ℒ:
L
=
1
n
∑
i
=
0
n
(
w
x
(
i
)
+
b
−
y
(
i
)
)
2
\mathcal{L}=\frac{1}{n} \sum_{i=0}^{n}\left(w x^{(i)}+b-y^{(i)}\right)^{2}
L=n1i=0∑n(wx(i)+b−y(i))2
需要优化的模型参数是𝑤和𝑏,因此我们按照
w
′
=
w
−
η
∂
L
∂
w
w^{\prime}=w-\eta \frac{\partial \mathcal{L}}{\partial w}
w′=w−η∂w∂L
b
′
=
b
−
η
∂
L
∂
b
b^{\prime}=b-\eta \frac{\partial \mathcal{L}}{\partial b}
b′=b−η∂b∂L
方式循环更新参数。
2.3 线性模型实战
在介绍了用于优化𝑤和𝑏的梯度下降算法后,我们来实战训练单输入神经元线性模型。首先我们需要采样自真实模型的多组数据,对于已知真实模型的玩具样例(Toy Example),我们直接从指定的𝑤 = 1.477 , 𝑏 = 0.089 的真实模型中直接采样:
y
=
1.477
∗
x
+
0.089
y=1.477 * x+0.089
y=1.477∗x+0.089
1. 采样数据
为了能够很好地模拟真实样本的观测误差,我们给模型添加误差自变量𝜖,它采样自均值为 0,方差为 0.01 的高斯分布:
y
=
1.477
x
+
0.089
+
ϵ
,
ϵ
∼
N
(
0
,
0.01
)
y=1.477 x+0.089+\epsilon, \epsilon \sim \mathcal{N}(0,0.01)
y=1.477x+0.089+ϵ,ϵ∼N(0,0.01)
通过随机采样𝑛 = 100 次,我们获得𝑛个样本的训练数据集𝔻train:
import numpy as np
data=[] #保存样本集的列表
for i in range(100): #循环采样100个点
x=np.random.uniform(-10.,10.) #随机采样输入x
# 采样高斯噪声
eps=np.random.normal(0.,0.1) # 均值和方差
# 得到模型的输出
y=1.477*x+0.089+eps
data.append([x,y]) #保存样本点
data=np.array(data)# 转换为2D Numpy数组
print(data)
循环进行 100 次采样,每次从均匀分布U( -10,10)中随机采样一个数据𝑥,同时从均值为 0,方差为 0. 1 2 0.1^{2} 0.12的高斯分布 N ( 0 , 0. 1 2 ) \mathcal{N}\left(0,0.1^{2}\right) N(0,0.12)中随机采样噪声𝜖,根据真实模型生成𝑦的数据,并保存为 Numpy数组。
2. 计算误差
循环计算在每个点
(
x
(
i
)
,
y
(
i
)
)
\left(x^{(i)}, y^{(i)}\right)
(x(i),y(i))处的预测值与真实值之间差的平方并累加,从而获得训练集上的均方差损失值.
def mse(b,w,points):
totalError=0 # 根据当前的w,b参数计算均方差损失
for i in range(0,len(points)): # 循环迭代所有点
x=points[i,0] #获得i号点的输入x
y=points[i,1] #获得i号点的输出y
# 计算差的平方,并累加
totalError+=(y-(w*x+b))**2
# 将累加的误差求平均,得到均方误差
return totalError/float(len(points))
最后的误差和除以数据样本总数,从而得到每个样本上的平均误差。
3. 计算梯度
根据之前介绍的梯度下降算法,我们需要计算出函数在每一个点上的梯度信息:
(
∂
L
∂
w
,
∂
L
∂
b
)
\left(\frac{\partial \mathcal{L}}{\partial w}, \frac{\partial \mathcal{L}}{\partial b}\right)
(∂w∂L,∂b∂L)。我们来推导一下梯度的表达式,首先考虑
∂
L
∂
w
\frac{\partial \mathcal{L}}{\partial w}
∂w∂L,将均方差函数展开:
∂
L
∂
w
=
∂
1
n
∑
i
=
1
n
(
w
x
(
i
)
+
b
−
y
(
i
)
)
2
∂
w
=
1
n
∑
i
=
1
n
∂
(
w
x
(
i
)
+
b
−
y
(
i
)
)
2
∂
w
\frac{\partial \mathcal{L}}{\partial w}=\frac{\partial \frac{1}{n} \sum_{i=1}^{n}\left(w x^{(i)}+b-y^{(i)}\right)^{2}}{\partial w}=\frac{1}{n} \sum_{i=1}^{n} \frac{\partial\left(w x^{(i)}+b-y^{(i)}\right)^{2}}{\partial w}
∂w∂L=∂w∂n1∑i=1n(wx(i)+b−y(i))2=n1i=1∑n∂w∂(wx(i)+b−y(i))2
考虑到
∂
g
2
∂
w
=
2
⋅
g
⋅
∂
g
∂
w
\frac{\partial g^{2}}{\partial w}=2 \cdot g \cdot \frac{\partial g}{\partial w}
∂w∂g2=2⋅g⋅∂w∂g
因此
如果难以理解上述推导,可以复习数学中函数的梯度相关课程,同时在本书第 7 章也会详细介绍,我们可以记住
∂
L
∂
w
\frac{\partial \mathcal{L}}{\partial w}
∂w∂L的最终表达式即可。用同样的方法,我们可以推导偏导数
∂
L
∂
b
\frac{\partial \mathcal{L}}{\partial b}
∂b∂L的表达式:
根据上面偏导数的表达式,我们只需要计算在每一个点上面的 ( w x ( i ) + b − y ( i ) ) \left(w x^{(i)}+b-y^{(i)}\right) (wx(i)+b−y(i))* x ( i ) x^{(i)} x(i)和 ( w x ( i ) + b − y ( i ) ) \left(w x^{(i)}+b-y^{(i)}\right) (wx(i)+b−y(i))值,平均后即可得到偏导数 ∂ L ∂ w \frac{\partial \mathcal{L}}{\partial w} ∂w∂L和 ∂ L ∂ b \frac{\partial \mathcal{L}}{\partial b} ∂b∂L。实现如下:
def step_gradient(b_current,w_current,points,lr):
# 计算误差函数在所有点上的异数,并更新w,b
b_gradirnt=0
w_gradient=0
M=float(len(points))# 总体样本
for i in range(0,len(points)):
x=points[i,0]
y=points[i,1]
# 误差函数对b的导数;grad_b=2(wx+b-y)
b_gradirnt+=(2/M) *((w_current*x+b_current)-y)
# 误差函数对w的求导:grad_w=2(wx+b-y)*x
w_gradient=w_gradient+(2/M)*x*((w_current*x+b_current)-y)
# 根据梯度下降算法更新的 w',b',其中lr为学习率
new_b=b_current-(lr*b_gradirnt)
new_w=w_current-(lr*w_gradient)
return [new_b,new_w]
4. 梯度更新
在计算出误差函数在𝑤和𝑏处的梯度后,我们可以根据公式来更新𝑤和𝑏的值。我们把对数据集的所有样本训练一次称为一个 Epoch,共循环迭代 num_iterations 个 Epoch。实现如下:
def gradient_descent(points,starting_b,starting_w,lr,num_iterations):
# 循环更新w,b多次
b=starting_b #b的初始值
w=starting_w #w的初始值
#根据梯度下降算法更新多次
for step in range(num_iterations):
# 计算梯度并跟新一次
b,w=step_gradient(b,w,np.array(points),lr)
loss=mse(b,w,points) #计算当前的均方误差,用于监控训练进度
if step%50==0: #打印误差和实时的w,b值
print("iteration:{},loss:{},w:{},b:{}".format(step,loss,w,b))
return [b,w] #返回最后一次的w,b
主训练函数实现如下:
def main():
# 加载训练数据集,这些数据是通过真实模型添加观测误差采集的到的
lr=0.01 # 学习率
initial_b=0 # 初始化b为0
initial_w=0 # 初始化w为0
num_iteration=1000
# 训练优化1000次,返回最优 w*,b*和训练Loss的下降过程
[b,w],losses=gradient_descent(data,initial_b,initial_w,lr,num_iteration)
loss=mse(b,w,data)# 计算最优数值w,b的均方误差
print('Final loss:{},w:{},b:{}'.format(loss,w,b))
经过 1000 的迭代更新后,保存最后的𝑤和𝑏值,此时的𝑤和𝑏的值就是我们要找的 w ∗ , b ∗ w^{*}, b^{*} w∗,b∗数值解。运行结果如下:
iteration:0,loss:7.969113186146375,w:0.9913396896581235,b:-0.011658714860303041
iteration:50,loss:0.01100388016184387,w:1.479069826409514,b:0.04491371458460997
iteration:100,loss:0.009850311759811367,w:1.479390036812964,b:0.0681094917719914
iteration:150,loss:0.00969537825863523,w:1.4795073877142864,b:0.076610294152195
iteration:200,loss:0.009674569445092486,w:1.4795503945432114,b:0.07972567332330503
iteration:250,loss:0.009671774654309519,w:1.4795661557117525,b:0.08086739935641314
iteration:300,loss:0.009671399291461264,w:1.4795719318742826,b:0.08128581979998706
iteration:350,loss:0.009671348877216069,w:1.4795740487258022,b:0.0814391627759057
iteration:400,loss:0.009671342106178024,w:1.4795748245108207,b:0.08149536000198461
iteration:450,loss:0.009671341196773231,w:1.4795751088209812,b:0.08151595519521115
iteration:500,loss:0.00967134107463287,w:1.4795752130151398,b:0.08152350293401668
iteration:550,loss:0.00967134105822844,w:1.4795752512002776,b:0.08152626903387541
iteration:600,loss:0.009671341056025198,w:1.47957526519439,b:0.08152728275581592
iteration:650,loss:0.00967134105572927,w:1.4795752703229608,b:0.08152765426524274
iteration:700,loss:0.009671341055689535,w:1.4795752722024824,b:0.0815277904162409
iteration:750,loss:0.009671341055684193,w:1.4795752728912905,b:0.08152784031294075
iteration:800,loss:0.009671341055683477,w:1.4795752731437255,b:0.0815278585991133
iteration:850,loss:0.009671341055683385,w:1.479575273236238,b:0.08152786530064077
iteration:900,loss:0.009671341055683366,w:1.479575273270142,b:0.08152786775662066
iteration:950,loss:0.00967134105568336,w:1.479575273282567,b:0.0815278686566896
Final loss:0.009671341055683385,w:1.4795752732870673,b:0.08152786898267782
可以看到,第 100 次迭代时,𝑤和𝑏的值就已经比较接近真实模型了,更新 1000 次后得到的
w
∗
,
b
∗
w^{*}, b^{*}
w∗,b∗数值解与真实模型的非常接近,训练过程的均方差变化曲线如图 2.7 所示。
上述例子比较好地展示了梯度下降算法在求解模型参数上的强大之处。需要注意的是,对于复杂的非线性模型,通过梯度下降算法求解到的𝑤和𝑏可能是局部极小值而非全局最小值解,这是由模型函数的非凸性决定的。但是我们在实践中发现,通过梯度下降算法求得的数值解,它的性能往往都能优化得很好,可以直接使用求解到的数值解𝑤和𝑏来近似作为最优解。
2.4 线性回归
简单回顾一下我们的探索之路:首先假设𝑛个输入的生物神经元的数学模型为线性模型之后,只采样𝑛 + 1个数据点就可以估计线性模型的参数𝒘和𝑏。引入观测误差后,通过梯度下降算法,我们可以采样多组数据点循环优化得到𝒘和𝑏的数值解。
如果我们换一个角度来看待这个问题,它其实可以理解为一组连续值(向量)的预测问题。给定数据集𝔻,我们需要从𝔻中学习到数据的真实模型,从而预测未见过的样本的输出值。在假定模型的类型后,学习过程就变成了搜索模型参数的问题,比如我们假设神经元为线性模型,那么训练过程即为搜索线性模型的𝒘和𝑏参数的过程。训练完成后,利用学到的模型,对于任意的新输入𝒙,我们就可以使用学习模型输出值作为真实值的近似。从这个角度来看,它就是一个连续值的预测问题。
在现实生活中,连续值预测问题是非常常见的,比如股价的走势预测、天气预报中温度和湿度等的预测、年龄的预测、交通流量的预测等。对于预测值是连续的实数范围,或者属于某一段连续的实数区间,我们把这种问题称为回归(Regression)问题。特别地,如果使用线性模型去逼近真实模型,那么我们把这一类方法叫做线性回归(Linear Regression,简称 LR),线性回归是回归问题中的一种具体的实现。
除了连续值预测问题以外,是不是还有离散值预测问题呢?比如说硬币正反面的预测,它的预测值𝑦只可能有正面或反面两种可能;再比如说给定一张图片,这张图片中物体的类别也只可能是像猫、狗、天空之类的离散类别值。对于这一类问题,我们把它称为分类(Classification)问题。接下来我们来挑战分类问题吧!