基本介绍 {#sec:basic}
假定数据集合中有
m
m
m个样本点,对于每一个样本点
x
i
x_i
xi,具有值
y
i
y_i
yi,且
x
=
{
x
i
∣
i
∈
{
0
,
1
,
…
,
m
−
1
}
}
x = \{x_i | i \in \{0, 1, \ldots, m-1\} \}
x={xi∣i∈{0,1,…,m−1}}与结果
y
=
{
y
i
∣
i
∈
{
0
,
1
,
…
,
m
−
1
}
}
y = \{y_i |i \in \{0, 1, \ldots, m-1\} \}
y={yi∣i∈{0,1,…,m−1}}呈现线性关系。
我们的目标是根据现有的
m
m
m个样本,拟合出一条直线,即
y
=
w
∗
x
+
b
(1)
y = w * x + b \tag{1}
y=w∗x+b(1)
使得根据这条直线得到的结果与真实的结果误差最小。那么如何来衡量这个误差呢?我们引入平方损失函数,即对于样本
x
i
x_i
xi,我们有误差
J
i
J_i
Ji
J
i
=
(
w
∗
x
i
+
b
−
y
i
)
2
J_i = (w*x_i+b - y_i)^2
Ji=(w∗xi+b−yi)2 因此,全部
m
m
m个样本的平均误差为:
J
=
1
m
∑
i
=
0
m
−
1
J
i
J = \frac{1}{m}\sum_{i=0}^{m-1}{J_i}
J=m1i=0∑m−1Ji
从数学上表述为,我们要求得
w
w
w和
b
b
b ,使得
j
j
j最小,即
arg
min
1
m
∑
i
=
0
m
−
1
J
i
\arg \min \frac{1}{m}\sum_{i=0}^{m-1}{J_i}
argminm1i=0∑m−1Ji
针对于最小化特定方程的,我们区分为几个section来介绍。
普通求导 {#par:simple}
根据多元函数求极值得方法,直接分别对
w
w
w和
b
b
b求偏导,且使得偏导为0,即:
∂
J
∂
w
=
0
,
∂
J
∂
b
=
0
\frac{\partial J}{\partial w} = 0, \ \ \ \frac{\partial J}{\partial b} = 0
∂w∂J=0, ∂b∂J=0
只有两个未知数,两个等式,因此可以解出
w
,
b
w,b
w,b。
但是,这里面假定了样本点
x
i
x_i
xi只有一列属性,也就是说每一个样本都可以在一个二维图像中描绘出来。当一个样本具有
n
n
n列属性的时候,上述就会有
n
+
1
n+1
n+1个等式,即:
∂
J
∂
w
0
=
0
,
…
,
∂
J
∂
w
n
−
1
=
0
,
∂
J
∂
b
=
0
\frac{\partial J}{\partial w_0} = 0, \ \ \ldots,\ \ \frac{\partial J}{\partial w_{n-1}} = 0, \ \ \ \frac{\partial J}{\partial b} = 0
∂w0∂J=0, …, ∂wn−1∂J=0, ∂b∂J=0
这样联立线性方程组求解非常复杂.
向量求导
当未特殊说明,向量一律为列向量。
对于具有多个属性的
x
i
x_i
xi,我们拟合的公式
(
1
)
(1)
(1)可以转化为:
y
=
w
T
x
+
b
y = w^T x + b
y=wTx+b
为了统一化,我们将
w
,
b
w,b
w,b合并为向量
θ
\theta
θ,并给
x
i
x_i
xi增加额外的一个属性,值为1.
这样我们有: y = θ T x = x T θ y = \theta^T x = x^T \theta y=θTx=xTθ
此时,平均误差公式可以进一步简化为:
J
(
θ
)
=
1
m
∑
i
=
0
m
−
1
(
x
i
T
θ
−
y
i
)
2
=
1
m
(
X
θ
−
Y
)
T
(
X
θ
−
Y
)
\begin{aligned} J(\theta) &= \frac{1}{m} \sum_{i=0}^{m-1}( x_i^T \theta - y_i)^2 \\ &= \frac{1}{m} (X \theta - Y)^T (X \theta - Y)\end{aligned}
J(θ)=m1i=0∑m−1(xiTθ−yi)2=m1(Xθ−Y)T(Xθ−Y)
其中
X
=
[
x
0
T
x
1
T
⋮
x
m
−
1
T
]
X = \begin{bmatrix} x_0^T\\ x_1^T\\ \vdots \\ x_{m-1}^T \end{bmatrix}
X=
x0Tx1T⋮xm−1T
,且
Y
=
[
y
0
y
1
⋮
y
m
−
1
]
Y= \begin{bmatrix} y_0\\ y_1\\ \vdots\\ y_{m-1} \end{bmatrix}
Y=
y0y1⋮ym−1
我们的目标是求得最小化
J
(
θ
)
J(\theta)
J(θ)时的
θ
\theta
θ值,这可通过向量求导:
∂
J
(
θ
)
∂
θ
=
0
(2)
\tag{2} \frac{\partial J(\theta)} {\partial \theta} = 0
∂θ∂J(θ)=0(2)
为了对公式
(
2
)
(2)
(2)进行求解,我们首先引入几个基本向量求导公式:
∂
x
T
a
∂
x
=
∂
a
x
T
∂
x
=
a
∂
x
T
B
x
∂
x
=
(
B
+
B
T
)
x
\begin{aligned} \frac{\partial x^T a}{\partial x} &= \frac{\partial a x^T}{\partial x} = a \\ \frac{\partial x^T B x}{\partial x} &= (B + B^T) x\end{aligned}
∂x∂xTa∂x∂xTBx=∂x∂axT=a=(B+BT)x
对于上述的基本求导公式,它的证明只有一个思想:数对向量求导,相当于此数对向量中的各个元素逐个求导。上述的两个公式都是对列向量
x
x
x求导,因此结果仍然是一个列向量。
上述公式的简单记忆方法: 前导不变,后导转置,公式表达为:
∂
x
T
a
∂
x
=
a
,
∂
b
x
∂
x
=
b
T
\frac{\partial x^T a}{\partial x} = a, \ \ \ \frac{\partial b x}{\partial x} = b^T
∂x∂xTa=a, ∂x∂bx=bT
注意: 这里的
b
b
b是行向量。
令
Z
(
θ
)
=
(
X
θ
−
Y
)
T
(
X
θ
−
Y
)
Z(\theta) = (X \theta - Y)^T (X \theta - Y)
Z(θ)=(Xθ−Y)T(Xθ−Y),
则
J
(
θ
)
=
1
m
Z
(
θ
)
J(\theta) = \frac{1}{m}Z(\theta)
J(θ)=m1Z(θ),且
Z
(
θ
)
=
(
θ
T
X
T
−
Y
T
)
(
X
θ
−
Y
)
=
θ
T
X
T
X
θ
−
θ
T
X
T
Y
−
Y
T
X
θ
+
Y
T
Y
\begin{aligned} Z(\theta) &= (\theta^T X^T - Y^T) (X \theta - Y) \\ &= \theta^T X^T X \theta - \theta^T X^T Y - Y^T X \theta + Y^TY\end{aligned}
Z(θ)=(θTXT−YT)(Xθ−Y)=θTXTXθ−θTXTY−YTXθ+YTY
因此我们有: ∂ ( Z ( θ ) ) ∂ θ = ( X T X + X T X ) θ − X T Y − X T Y + 0 = 2 X T X θ − 2 X T Y \begin{aligned} \frac{\partial {(Z(\theta))}} {\partial \theta} &= (X^TX + X^TX) \theta - X^TY - X^TY + 0 \\ &= 2X^TX \theta - 2 X^T Y \end{aligned} ∂θ∂(Z(θ))=(XTX+XTX)θ−XTY−XTY+0=2XTXθ−2XTY
代入 Z ( θ ) Z(\theta) Z(θ)到公式 ( 2 ) (2) (2),我们有: ∂ ( 1 m Z ( θ ) ) ∂ θ = 0 即: 1 m ( 2 X T X θ − 2 X T Y ) = 0 即: X T X θ − X T Y = 0 \begin{aligned} \frac{\partial {(\frac{1}{m}Z(\theta))}} {\partial \theta} &= 0 \\ \text{即:} \frac{1}{m}(2X^TX \theta - 2 X^T Y ) &= 0 \\ \text{即:} X^TX \theta - X^T Y &= 0\end{aligned} ∂θ∂(m1Z(θ))即:m1(2XTXθ−2XTY)即:XTXθ−XTY=0=0=0
如果 X T X X^T X XTX可逆,那么我们有: θ = ( X T X ) − 1 X T Y \theta = (X^TX)^{-1} X^TY θ=(XTX)−1XTY
上述的优化方法需要计算矩阵的逆,当数据量很小而且可逆的时候,速度快,效果好,但是并不适用于大量高维度的数据。是否有一些数学中的迭代的方式能不断的逼近最小值呢?这个答案有很多,下面将尽力逐个介绍。
梯度下降
梯度下降,顾名思义就是顺着梯度的方向的反方向下滑,直到滑动到某一个最低点为止。
我们可以把它想象成一个小山,如下图所示(
很抱歉是用latex写的,画图采用的tikz,第一次用不熟练,很丑),假定我们的起始点为start,然后顺着下山的方向,一步一步的就会滑落到它左边的最低点。
这可能会有一个问题: 如果它的右边有一个更低的最低点呢?
它有可能落不到全局最低,但是可以达到局部最低。不过,如果我们的函数是凸函数,也就是说只有一个极值点的时候,它的局部最优也就是全局最优了。
原理篇
一维直观篇
为了与高等数学教材的保持一致,采用书里面的记法,在
△
x
→
0
\triangle x \to 0
△x→0时,我们有:
f
(
x
+
△
x
)
=
f
(
x
)
+
△
x
⋅
f
′
(
x
)
+
o
(
△
x
)
f(x+ \triangle x) = f(x) + \triangle x \cdot f'(x) + \textit{o}(\triangle x)
f(x+△x)=f(x)+△x⋅f′(x)+o(△x)
此后我们简单的忽略
o
(
△
x
)
\textit{o}(\triangle x)
o(△x)这一项。
令上图中的start点的横坐标为
x
0
x_0
x0,代入
x
=
x
0
x=x_0
x=x0,我们有:
f
(
x
0
+
△
x
)
=
f
(
x
0
)
+
△
x
⋅
f
′
(
x
0
)
f(x_0+ \triangle x) = f(x_0) + \triangle x \cdot f'(x_0)
f(x0+△x)=f(x0)+△x⋅f′(x0)
为了使它向着小山下方(左面)滑动,我们需要有
f
(
x
0
+
△
x
)
<
f
(
x
0
)
f(x_0 + \triangle x) < f(x_0)
f(x0+△x)<f(x0),即
△
x
⋅
f
′
(
x
0
)
<
0
\triangle x \cdot f'(x_0) < 0
△x⋅f′(x0)<0
那么
△
x
\triangle x
△x需要满足什么条件呢?我们令
g
=
f
′
(
x
)
,
σ
=
△
x
g=f'(x),\ \ \sigma = \triangle x
g=f′(x), σ=△x,我们有:
△
x
⋅
f
′
(
x
0
)
=
g
⋅
σ
\triangle x \cdot f'(x_0) = g \cdot \sigma
△x⋅f′(x0)=g⋅σ
很显然,我们只需要
σ
\sigma
σ取得
g
g
g的相反的方向,例如
σ
=
−
0.01
g
\sigma = -0.01g
σ=−0.01g,即可满足
g
⋅
σ
<
0
g \cdot \sigma < 0
g⋅σ<0。请原谅我,虽然进行
g
g
g和
σ
\sigma
σ的定义看起来多此一举,但请相信我,当将其映射到高维的时候,它能更好的帮助理解。
负梯度:这里面的 g g g是斜率,其实也是梯度。 σ \sigma σ与 g g g变化方向相反,因此我们称之为 x x x沿着梯度下降的方向,也就是负梯度方向。
学习率:
上面我们说
σ
\sigma
σ只需要与梯度的方向相反,那么
σ
=
−
0.1
g
,
σ
=
−
0.01
g
\sigma = -0.1g, \ \ \sigma = -0.01g
σ=−0.1g, σ=−0.01g都可以满足要求,因此我们使用变量
α
\alpha
α表达学习率的概念,即
σ
=
−
α
⋅
g
\sigma = -\alpha \cdot g
σ=−α⋅g。
你应该已经知道学习率为何不能太大的原因了吧,上面的描述都是基于 σ = △ x → 0 \sigma = \triangle x \to 0 σ=△x→0的情况下,进行的推导,在实际中我们通常不会选用太大的 α \alpha α,不过太小的 α \alpha α意味着学习速度变慢,也就是说需要迭代更多的步数才可以到达最小值。
假定学习率
α
=
0.01
\alpha = 0.01
α=0.01,从而我们有迭代公式:
x
1
=
x
0
−
0.01
g
,
…
,
x
n
+
1
=
x
n
−
0.01
g
x_1 = x_0 -0.01g,\ \ \ \ldots, \ \ \ x_{n+1} = x_n -0.01g
x1=x0−0.01g, …, xn+1=xn−0.01g
利用如上的递推公式,我们就可以不断的使得 f ( x n + 1 ) < f ( x n ) f(x_{n+1}) < f(x_n) f(xn+1)<f(xn),即不断下滑到最低点。
二维梯度篇
我先从二维逐步扩展到高维的形式,二维的微分形式:
f
(
x
+
△
x
,
y
+
△
y
)
=
f
(
x
,
y
)
+
△
x
f
′
(
x
)
+
△
y
f
′
(
y
)
+
o
(
△
2
x
+
△
2
y
)
f(x+\triangle x, y+ \triangle y) = f(x, y) + \triangle x f'(x) + \triangle y f'(y) + \textit{o}(\sqrt{\triangle ^2 x + \triangle^2 y})
f(x+△x,y+△y)=f(x,y)+△xf′(x)+△yf′(y)+o(△2x+△2y)
我们的目标是使得在对于自变量
x
,
y
x, y
x,y进行相应的
△
x
,
△
y
\triangle x, \triangle y
△x,△y变化后,新的
f
(
x
+
△
x
,
y
+
△
y
)
f(x+\triangle x, y+ \triangle y)
f(x+△x,y+△y)能够更小,也就是说使得:
△
x
f
′
(
x
)
+
△
y
f
′
(
y
)
+
o
(
△
2
x
+
△
2
y
)
<
0
\triangle x f'(x) + \triangle y f'(y) + \textit{o}(\sqrt{\triangle ^2 x + \triangle^2 y}) < 0
△xf′(x)+△yf′(y)+o(△2x+△2y)<0
那
△
x
,
△
y
\triangle x, \triangle y
△x,△y需要满足什么条件呢?
我们令
g
T
=
(
f
′
(
x
)
,
f
′
(
y
)
)
,
σ
T
=
(
△
x
,
△
y
)
g^T = (f'(x), f'(y) ), \sigma ^T = (\triangle x, \triangle y)
gT=(f′(x),f′(y)),σT=(△x,△y),我们有:
△
x
f
′
(
x
)
+
△
y
f
′
(
y
)
=
g
T
⋅
σ
=
∣
∣
g
∣
∣
⋅
∣
∣
σ
∣
∣
⋅
c
o
s
(
θ
)
\triangle x f'(x) + \triangle y f'(y) = g^T \cdot \sigma = ||g|| \cdot ||\sigma|| \cdot cos(\theta)
△xf′(x)+△yf′(y)=gT⋅σ=∣∣g∣∣⋅∣∣σ∣∣⋅cos(θ)
很显然,我们应该使得
c
o
s
(
θ
)
=
−
1
cos(\theta) = -1
cos(θ)=−1,也就是说
σ
\sigma
σ的方向与梯度
g
g
g的方向相反。
如果加上学习率,我们可以令
σ
=
−
α
⋅
g
\sigma = -\alpha \cdot g
σ=−α⋅g.
同样,与一维的情况一样,也是沿着负梯度的方向。
高维梯度篇
我们终于来到了高维情况,直接利用前面叙述的参数,梯度
g
g
g,学习率
α
\alpha
α,自变量变化
σ
\sigma
σ,注意
σ
\sigma
σ是一个向量,它代表各个自变量参数的变化情况,可简单把它想象成
{
△
x
,
△
y
,
⋯
}
\{\triangle x, \triangle y, \cdots\}
{△x,△y,⋯}。
我们有:
f
(
X
+
σ
)
=
f
(
X
)
+
g
T
⋅
σ
+
o
(
∣
∣
σ
∣
∣
)
f(X + \sigma) = f(X) + g^T \cdot \sigma + \textit{o}(||\sigma||)
f(X+σ)=f(X)+gT⋅σ+o(∣∣σ∣∣)
同样,我们应该有 σ = − α ⋅ g \sigma = -\alpha \cdot g σ=−α⋅g。
梯度下降简单实现demo篇
看到这里,有没有想实现一个梯度下降的冲动,反正我是有的,因此,我用python写了一个非常非常基本的二维的梯度下降,来实现线性回归。
请稍微回到我们在section 1.1中介绍的平面图上的m个点
(
x
i
,
y
i
)
(x_i, y_i)
(xi,yi),且呈现线性关系,我们的平均误差方程为:
J
(
w
,
b
)
=
1
m
∑
i
=
0
m
−
1
J
i
J(w,b) = \frac{1}{m}\sum_{i=0}^{m-1}{J_i}
J(w,b)=m1i=0∑m−1Ji
其中
J
i
(
w
,
b
)
=
(
w
∗
x
i
+
b
−
y
i
)
2
J_i(w,b) = (w*x_i+b - y_i)^2
Ji(w,b)=(w∗xi+b−yi)2。我们的目标是解出
w
,
b
w,b
w,b以使得
J
J
J最小。
梯度下降的4个要素:
-
初始值 w 0 = 0 , b 0 = 0 w_0=0, b_0=0 w0=0,b0=0
-
学习率 α = 0.01 → 0.0001 \alpha = 0.01 \to 0.0001 α=0.01→0.0001
-
梯度 ∂ J ( w , b ) ∂ w = 1 m ∑ i = 0 m − 1 2 ( w x i + b − y i ) x i ∂ J ( w , b ) ∂ b = 1 m ∑ i = 0 m − 1 2 ( w x i + b − y i ) \begin{aligned} \frac{\partial J(w,b)} {\partial w} &= \frac{1}{m} \sum_{i=0}^{m-1} {2(wx_i+b-y_i)x_i} \\ \frac{\partial J(w,b)} {\partial b} &= \frac{1}{m} \sum_{i=0}^{m-1} {2(wx_i+b-y_i)} \end{aligned} ∂w∂J(w,b)∂b∂J(w,b)=m1i=0∑m−12(wxi+b−yi)xi=m1i=0∑m−12(wxi+b−yi)
-
梯度更新 w n + 1 = w n − α ⋅ ∂ J ( w , b ) ∂ w b n + 1 = b n − α ⋅ ∂ J ( w , b ) ∂ b \begin{aligned} w_{n+1} &= w_{n} - \alpha \cdot \frac{\partial J(w,b)} {\partial w} \\ b_{n+1} &= b_{n} - \alpha \cdot \frac{\partial J(w,b)} {\partial b} \end{aligned} wn+1bn+1=wn−α⋅∂w∂J(w,b)=bn−α⋅∂b∂J(w,b)
我们使用的数据点如下面的散点图所示,它是使用 w = 2 , b = 3 w=2, b=3 w=2,b=3的公式在 x ∈ { 0 , 1 , … , 99 } x \in \{0, 1, \ldots, 99 \} x∈{0,1,…,99}中加入一定的随机数得到的。
生出散点图的python代码如下
import numpy as np
import random
import matplotlib.pyplot as plt
import pdb
random.seed(10)
x = np.arange(100)
w, b = 2, 3
y = np.array([w * i + b + random.randint(-5,5) for i in x])
one = np.ones(len(x))
plt.plot(x, y, '.')
plt.show()
利用梯度下降的4个要素编写的代码如下:
#alpha and g
alpha = 0.0003
w0, b0 = 0, 0
def gradient_w(w, b):
return np.average([2*(w*xi + b - yi)* xi for (xi, yi) in list(zip(x,y))])
def gradient_b(w, b):
return np.average([2*(w*xi + b - yi) for (xi, yi) in list(zip(x,y))])
for i in range(100000):
w1 = w0 - alpha * gradient_w(w0, b0)
b1 = b0 - alpha * gradient_b(w0, b0)
w0, b0 = w1, b1
plt.plot(x, y, 'k+')
plt.plot(x, w0 * x + b0, 'r')
plt.show()
最终迭代出的结果为: w 1 = 1.99700571226 b 1 = 3.19821704612 w1 = 1.99700571226 b1 = 3.19821704612 w1=1.99700571226b1=3.19821704612
画出的曲线如下图所示
代码其实几分钟就写完了,但是一直都拟合不出来,当时我设置的学习率为 a l p h a = 0.001 alpha=0.001 alpha=0.001,还没有迭代多少步,就出现了值无穷大(nan)的情况,我一直以为是代码有问题,检查了一遍又一遍,还是感觉代码没问题,后来直到调整了学习率之后,才能够正确拟合出结果。
学习率的影响:
学习率过小,导致学习速度过慢,如果设置了最大迭代次数,那么很有可能还没有学到最终结果的时候,就已经终止了。不过我们可以看到它的误差,即
J
(
w
,
b
)
J(w,b)
J(w,b)是呈现一个不断下降的趋势。
学习率过大,虽然学习速度上去了,但是很有可能跳出了最优解,这可能会导致算法最终并不会收敛,误差通常会溢出。
我从网上盗取了两张图,来分别展示学习率大小对结果的影响。


对于学习率引起的问题,我给上述的梯度下降代码加入了误差计算并存储,并画出误差图。
在使用学习率
α
=
0.00001
\alpha = 0.00001
α=0.00001,迭代2000次后,我们得到
w
1
=
2.04427897398
,
b
1
=
0.0626663170812
w1 = 2.04427897398,\ b1 = 0.0626663170812
w1=2.04427897398, b1=0.0626663170812,可以看出这与实际的
w
=
2
,
b
=
3
w=2, b=3
w=2,b=3还是有不小的差距的,其误差画出曲线如误差图中的左图所示。
在使用学习率
α
=
0.001
\alpha = 0.001
α=0.001,迭代2000次后,我们得到
w
1
=
n
a
n
,
b
1
=
n
a
n
,
e
r
r
o
r
=
n
a
n
w1 = nan, b1 = nan, error = nan
w1=nan,b1=nan,error=nan,它的误差如误差图的右图所示。
根据误差图,就可以很容易指导我们是学习率不够,迭代次数不够,还是学习率过大。当误差依然处于下降的趋势,我们的迭代次数通常是不够的,如果时间不允许,那么可以稍微调整学习率,使用更大的学习率来加快收敛,但是不能过大,以免出现误差不收敛。
牛顿法
牛顿法与梯度下降法具有很大的相似性,区别在于梯度下降是采用的一阶导数,而牛顿法采用的二阶导数。
一维直观篇
请拿上我们的高等数学中的泰勒展开,采用书里面的记法,在
△
x
→
0
\triangle x \to 0
△x→0时,我们有:
f
(
x
+
△
x
)
=
f
(
x
)
+
△
x
⋅
f
′
(
x
)
+
1
2
△
2
x
⋅
f
′
′
(
x
)
+
o
(
△
2
x
)
f(x+\triangle x) = f(x) + \triangle x \cdot f'(x) + \frac{1}{2}\triangle^2 x \cdot f''(x) + \textit{o}(\triangle^2 x)
f(x+△x)=f(x)+△x⋅f′(x)+21△2x⋅f′′(x)+o(△2x)
同样的,我们需要求得这样的 △ x \triangle x △x,以使得 f ( x + △ x ) f(x+\triangle x) f(x+△x)尽可能的小。回顾在梯度下降中,我们只是将泰勒展开到前面的两项,然后得到 △ x = − α ⋅ f ′ ( x ) \triangle x = -\alpha \cdot f'(x) △x=−α⋅f′(x)可以使得 f ( x + △ x ) f(x+\triangle x) f(x+△x)呈现下降趋势,即沿着负梯度的方向。
在牛顿法中,我们的泰勒展开到了
△
x
\triangle x
△x的平方项,这使得我们可以换个思路以最小化
f
(
x
+
△
x
)
f(x+\triangle x)
f(x+△x):将
△
x
\triangle x
△x当成未知量,公式
f
(
x
)
+
△
x
⋅
f
′
(
x
)
+
1
2
△
2
x
⋅
f
′
′
(
x
)
f(x) + \triangle x \cdot f'(x) + \frac{1}{2}\triangle^2 x \cdot f''(x)
f(x)+△x⋅f′(x)+21△2x⋅f′′(x)是一个一元二次方程,曲线的开口向上,因此我们有
△
x
=
−
f
′
(
x
)
f
′
′
(
x
)
\triangle x = -\frac{f'(x)}{f''(x)}
△x=−f′′(x)f′(x)使得
f
(
x
+
△
x
)
f(x+\triangle x)
f(x+△x)取得最小值。
它与梯度下降很大的不同在于梯度下降的
△
x
\triangle x
△x只要求方向与梯度方向相反即可,而牛顿法却可以精确的求出
△
x
\triangle x
△x的值。
高维原理篇
假定有n个自变量参数 { x 1 , x 2 , … , x n } \{x_1, x_2, \ldots, x_n\} {x1,x2,…,xn},,自变量变化 σ \sigma σ,注意 σ \sigma σ是一个向量,它代表各个自变量参数的变化情况,可简单把它想象成 { △ x 1 , △ x 2 , ⋯ } \{\triangle x_1, \triangle x_2, \cdots\} {△x1,△x2,⋯},这里我们还需要额外的一个 G G G,它表示对自变量的二阶导数。
我们有学习率 α \alpha α(这是一个数),梯度向量 g g g: g = [ ∂ f ∂ x 1 ∂ f ∂ x 2 ⋮ ∂ f ∂ x n ] g = \begin{bmatrix} \frac{\partial f}{\partial x_1} \\ \frac{\partial f}{\partial x_2} \\ \vdots\\ \frac{\partial f}{\partial x_n} \end{bmatrix} g= ∂x1∂f∂x2∂f⋮∂xn∂f 自变量的变化 σ \sigma σ: σ = [ △ x 1 △ x 2 ⋮ △ x n ] \sigma = \begin{bmatrix} \triangle x_1\\ \triangle x_2\\ \vdots \\ \triangle x_n \end{bmatrix} σ= △x1△x2⋮△xn 二阶导数矩阵hessian矩阵 G G G: G = [ ∂ 2 f ∂ x 1 2 , ∂ 2 f ∂ x 1 ∂ x 2 , … , ∂ 2 f ∂ x 1 ∂ x n ∂ 2 f ∂ x 2 ∂ x 1 , ∂ 2 f ∂ x 2 2 , … , ∂ 2 f ∂ x 2 ∂ x n ⋮ ∂ 2 f ∂ x n ∂ x 1 , ∂ 2 f ∂ x n ∂ x 2 , … , ∂ 2 f ∂ x n 2 ] G = \begin{bmatrix} \frac{\partial^2 f}{\partial x_1^2},\ \frac{\partial^2 f}{\partial x_1 \partial x_2}, \ldots, \frac{\partial^2 f}{\partial x_1 \partial x_n}\\ \frac{\partial^2 f}{\partial x_2 \partial x_1}, \frac{\partial^2 f}{\partial x_2^2}, \ldots, \frac{\partial^2 f}{\partial x_2 \partial x_n}\\ \vdots\\ \frac{\partial^2 f}{\partial x_n \partial x_1}, \frac{\partial^2 f}{\partial x_n \partial x_2}, \ldots, \frac{\partial^2 f}{ \partial x_n^2} \end{bmatrix} G= ∂x12∂2f, ∂x1∂x2∂2f,…,∂x1∂xn∂2f∂x2∂x1∂2f,∂x22∂2f,…,∂x2∂xn∂2f⋮∂xn∂x1∂2f,∂xn∂x2∂2f,…,∂xn2∂2f 可以看出 G G G是对称矩阵,即 G = G T G = G^T G=GT。
我们有:
f
(
X
+
σ
)
=
f
(
X
)
+
g
T
⋅
σ
+
1
2
σ
T
⋅
G
⋅
σ
+
o
(
∣
∣
σ
∣
∣
2
)
f(X + \sigma) = f(X) + g^T \cdot \sigma + \frac{1}{2}\sigma^T \cdot G \cdot \sigma + \textit{o}(||\sigma||^2)
f(X+σ)=f(X)+gT⋅σ+21σT⋅G⋅σ+o(∣∣σ∣∣2)
利用前面学到的向量求导公式,对
σ
\sigma
σ求导,使得导数为0,即
∂
f
(
X
+
σ
)
∂
σ
=
g
+
1
2
(
G
+
G
T
)
⋅
σ
=
g
+
G
⋅
σ
=
0
\begin{aligned} \frac{\partial f(X+\sigma)}{\partial \sigma} &= g + \frac{1}{2}(G+G^T) \cdot \sigma \\ &= g+G \cdot \sigma \\ &= 0\end{aligned}
∂σ∂f(X+σ)=g+21(G+GT)⋅σ=g+G⋅σ=0 因此,我们有:
σ
=
−
G
−
1
⋅
g
\sigma = - G^{-1} \cdot g
σ=−G−1⋅g
然后我们就可以利用得到的
σ
\sigma
σ,得到新的
X
n
e
w
=
X
+
σ
X_{new} = X + \sigma
Xnew=X+σ,进行下一步迭代。
牛顿法代码Demo篇
计算 g g g和 G G G的代码:
def gradient_w(w, b):
return np.average([2*(w*xi + b - yi)* xi for (xi, yi) in list(zip(x,y))])
def gradient_b(w, b):
return np.average([2*(w*xi + b - yi) for (xi, yi) in list(zip(x,y))])
def gradient_w_w(w, b):
return np.average([2 * xi * xi for (xi, yi) in list(zip(x, y))])
def gradient_w_b(w, b):
return np.average([2 * xi for (xi, yi) in list(zip(x, y))])
def gradient_b_w(w, b):
return np.average([2 * xi for (xi, yi) in list(zip(x,y))])
def gradient_b_b(w, b):
return np.average([2 for (xi, yi) in list(zip(x,y))])
def error(w, b):
return np.average([np.square(w*xi + b - yi) for (xi, yi) in list(zip(x,y))])
牛顿迭代的代码:
erros = [[], []]
for i in range(2000):
g = np.mat([gradient_w(w0, b0), gradient_b(w0, b0)]).T
G = np.mat([[gradient_w_w(w0, b0), gradient_w_b(w0, b0)], [gradient_b_w(w0, b0), gradient_b_b(w0, b0)]])
sigma = -G.I * g
w1 = w0 + sigma[0, 0]
b1 = b0 + sigma[1, 0]
erros[0].append(i)
erros[1].append(error(w1, b1))
w0, b0 = w1, b1
plt.plot(x, y, 'k+')
plt.plot(x, w0 * x + b0, 'r')
plt.show()
从误差结果看,它一次迭代就可以得到最小值,后经过@景宽提醒,牛顿法本身计算的就是二阶泰勒展开的值。我们上述的直线方程只有两个系数,它的三阶泰勒值就是0,因此二阶泰勒展开就是它的最小值了。
最小二乘法的最大似然解释
前面在Section基本介绍中,我们直接用平方损失函数来最小化来得到最优直线。那么,你是否有疑问,为什么平方损失函数最小就可以得到最优的直线,而不是绝对值损失,或者四次方损失呢?
这其实涉及到概率论中的最大似然估计.
上述的问题,可以转化为:对于
m
m
m个点形成的集合
D
=
{
d
1
,
d
2
,
…
,
d
m
}
D = \{d1, d2, \ldots, d_m\}
D={d1,d2,…,dm},我们需要拟合一条直线
h
h
h,以使得拟合的直线最切合这个数据集合
D
D
D,也就是说我们要最大化概率
P
(
h
∣
D
)
P(h|D)
P(h∣D)。
由贝叶斯公式
P
(
h
∣
D
)
=
P
(
D
∣
h
)
⋅
P
(
h
)
P
(
D
)
∝
P
(
D
∣
h
)
\begin{aligned} P(h | D) &= \frac{P(D|h) \cdot P(h)}{P(D)} \propto P(D|h)\end{aligned}
P(h∣D)=P(D)P(D∣h)⋅P(h)∝P(D∣h)
如果各个点相互独立,则
P
(
h
∣
D
)
∝
P
(
d
1
∣
h
)
⋅
P
(
d
2
∣
h
)
⋅
…
⋅
P
(
d
n
∣
h
)
P(h|D) \propto P(d_1|h) \cdot P(d_2|h) \cdot \ldots \cdot P(d_n |h)
P(h∣D)∝P(d1∣h)⋅P(d2∣h)⋅…⋅P(dn∣h)
对于
P
(
d
i
∣
h
)
P(d_i |h)
P(di∣h)表示的是在给定直线
h
h
h的情况下,具有点
d
i
d_i
di的概率。我们假设各个点的误差
△
y
i
=
y
i
‾
−
y
i
\triangle y_i = \overline{y_i}-y_i
△yi=yi−yi服从均值为0,方差为
σ
\sigma
σ的正态分布,也就是说,在给定直线
h
h
h的情况下,点
d
i
d_i
di出现的概率为服从:
P
(
d
i
∣
h
)
∝
e
−
△
2
y
i
2
σ
2
P(d_i | h) \propto e^{-\frac{\triangle^2 y_i}{2 \sigma^2}}
P(di∣h)∝e−2σ2△2yi
于是,我们有:
P
(
h
∣
D
)
∝
e
∑
i
=
1
m
(
−
△
2
y
i
2
σ
2
)
P(h|D) \propto e^{\sum_{i=1}^{m}(-\frac{\triangle^2 y_i}{2 \sigma^2})}
P(h∣D)∝e∑i=1m(−2σ2△2yi)
从而最大化 P ( h ∣ D ) P(h|D) P(h∣D),等价于最小化 ∑ i = 1 m ( △ 2 y i ) \sum_{i=1}^{m}(\triangle^2 y_i) ∑i=1m(△2yi),也就是前面说的最小化平方误差。
另一种说法:
对于样本点
d
i
d_i
di,对样本点的预测取决于参数
θ
\theta
θ的选取,且我们有
△
y
i
=
y
i
‾
−
y
i
\triangle y_i = \overline{y_i} -y_i
△yi=yi−yi
其中
y
i
‾
\overline{y_i}
yi是
y
i
y_i
yi的预测值,
y
i
y_i
yi为真实值,
△
y
i
\triangle y_i
△yi为误差。
一般我们认为误差服从正态分布,即
△
y
i
∼
N
(
0
,
σ
)
\begin{aligned} \triangle y_i \sim \textit{N}(0, \sigma)\end{aligned}
△yi∼N(0,σ)
现在我们需要选取
θ
\theta
θ,以使得取得
y
i
y_i
yi的概率最大,即
L
(
θ
)
=
∏
i
=
1
m
P
(
y
i
∣
θ
)
=
∏
i
=
1
m
1
2
π
σ
exp
(
−
△
2
y
i
2
σ
)
L(\theta) = \prod_{i=1}^{m} P(y_i | \theta) = \prod_{i=1}^m\frac{1}{\sqrt{2\pi}\sigma}\exp(-\frac{\triangle ^2 y_i}{2\sigma})
L(θ)=i=1∏mP(yi∣θ)=i=1∏m2πσ1exp(−2σ△2yi)
两边取
l
o
g
log
log,乘积变求和,因此同样转换为最小化
∑
i
=
1
m
(
△
2
y
i
)
\sum_{i=1}^{m}(\triangle^2 y_i)
∑i=1m(△2yi),也就是前面说的最小化平方误差。
参考文献:
https://www.cnblogs.com/21207-iHome/p/5222993.html
http://blog.youkuaiyun.com/ying_xu/article/details/51240291
https://www.cnblogs.com/happylion/p/4172632.html
http://blog.youkuaiyun.com/lydyangliu/article/details/9208635
http://www.fuzihao.org/blog/2014/06/13/为什么最小二乘法对误差的估计要用平方/
https://www.zhihu.com/question/20447622