以线性回归:
h
θ
=
θ
0
+
θ
1
x
h_{\theta} = {\theta}_{0} + {\theta}_{1}x
hθ=θ0+θ1x
的平方误差代价函数为例:
J
(
θ
)
=
1
2
m
∑
i
=
1
m
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
2
,
θ
=
(
θ
0
,
θ
1
)
J(\theta) = \frac{1}{2m}\sum_{i=1}^{m}(h_{\theta }(x^{(i)})-y^{(i)})^{2} ,{\theta} = ({\theta}_{0}, {\theta}_{1})
J(θ)=2m1i=1∑m(hθ(x(i))−y(i))2,θ=(θ0,θ1)
上述
J
(
θ
)
J(\theta)
J(θ) 是对整个数据集中的每个样本的预测值与真实值之间的误差的平方求和再取平均的结果。
去掉求和符号与
(
1
2
m
)
(\frac{1}{2m})
(2m1) ,对于每一个样本
(
x
i
,
y
i
)
(x^{i}, y^{i})
(xi,yi),都能唯一确定一个
J
i
(
θ
)
=
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
2
J_{i}(\theta) = (h_{\theta }(x^{(i)})-y^{(i)})^{2}
Ji(θ)=(hθ(x(i))−y(i))2 ,说明一点,
(
x
i
,
y
i
)
(x^{i}, y^{i})
(xi,yi) 是常量,
J
i
(
θ
)
J_{i}(\theta)
Ji(θ) 是关于
θ
{\theta}
θ 的函数。由于每个样本数据值上的差异,导致每个
J
i
(
θ
)
J_{i}(\theta)
Ji(θ) 都不同。假设在本例中的三个样本所确定的代价函数
J
i
(
θ
)
J_{i}(\theta)
Ji(θ) 图像如下所示:
将其放在同一坐标系下:
当然这并不是
J
(
θ
)
=
1
2
m
∑
i
=
1
m
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
2
J(\theta) = \frac{1}{2m}\sum_{i=1}^{m}(h_{\theta }(x^{(i)})-y^{(i)})^{2}
J(θ)=2m1∑i=1m(hθ(x(i))−y(i))2 的图像,也画不出
J
(
θ
)
J(\theta)
J(θ) 的图像,但我们可以假设它的图像是下面这样的,图像底部是等高线:
对于每个代价函数
J
i
(
θ
)
J_{i}(\theta)
Ji(θ) ,我们都可以利用梯度下降算法求得一个
(
θ
0
,
θ
1
)
(
i
)
({\theta}_{0}, {\theta}_{1})^{(i)}
(θ0,θ1)(i) 使得
J
i
(
θ
)
J_{i}(\theta)
Ji(θ) 最小,但我们最终的任务是求解唯一的一个
(
θ
0
,
θ
1
)
({\theta}_{0}, {\theta}_{1})
(θ0,θ1) ,使得其对所有样本的代价和
J
(
θ
)
J(\theta)
J(θ) 最小,假如这个使得对所有样本代价和
J
(
θ
)
J(\theta)
J(θ) 最小的
θ
=
(
a
,
b
)
{\theta} = (a, b)
θ=(a,b) ,如果上面三个都是正常的样本,不是噪音,那么分别使得这三个代价函数最小的每个
(
θ
0
,
θ
1
)
(
i
)
({\theta}_{0}, {\theta}_{1})^{(i)}
(θ0,θ1)(i) 一定都是在(a, b)附近,所以,在利用梯度下降算法求解每个
(
θ
0
,
θ
1
)
(
i
)
({\theta}_{0}, {\theta}_{1})^{(i)}
(θ0,θ1)(i) 的时候,虽然它们下降的路径不同,但大体的方向却是相同的。
每个
J
i
(
θ
)
=
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
2
J_{i}(\theta) = (h_{\theta }(x^{(i)})-y^{(i)})^{2}
Ji(θ)=(hθ(x(i))−y(i))2对
(
θ
0
,
θ
1
)
({\theta}_{0}, {\theta}_{1})
(θ0,θ1) 求偏导得到梯度:
∂
J
i
(
θ
)
∂
θ
0
=
2
⋅
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
\frac{\partial J_{i}(\theta )}{\partial \theta _{0}} = 2 \cdot (h_{\theta }(x^{(i)})-y^{(i)})
∂θ0∂Ji(θ)=2⋅(hθ(x(i))−y(i))
∂
J
i
(
θ
)
∂
θ
1
=
2
⋅
(
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
⋅
x
(
i
)
)
\frac{\partial J_{i}(\theta )}{\partial \theta _{1}} = 2 \cdot ((h_{\theta }(x^{(i)})-y^{(i)}) \cdot x^{(i)})
∂θ1∂Ji(θ)=2⋅((hθ(x(i))−y(i))⋅x(i))
由于是要求得唯一一个
(
θ
0
,
θ
1
)
({\theta}_{0}, {\theta}_{1})
(θ0,θ1) ,使得其对所有样本的代价和
J
(
θ
)
J(\theta)
J(θ) 最小,所以,对于batch(批量)梯度下降算法而言,做法是将每一个样本的梯度求和再取平均,这里为了方便计算,再在前面乘以
1
2
\frac{1}{2}
21 ,得到:
∂
J
(
θ
)
∂
θ
0
=
1
2
⋅
1
m
∑
i
=
1
m
(
∂
J
i
(
θ
)
∂
θ
0
)
=
1
m
∑
i
=
1
m
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
\frac{\partial J(\theta )}{\partial \theta _{0}} = \frac{1}{2} \cdot \frac{1}{m}\sum_{i=1}^{m}(\frac{\partial J_{i}(\theta )}{\partial \theta _{0}}) = \frac{1}{m}\sum_{i=1}^{m}(h_{\theta }(x^{(i)})-y^{(i)})
∂θ0∂J(θ)=21⋅m1i=1∑m(∂θ0∂Ji(θ))=m1i=1∑m(hθ(x(i))−y(i))
∂ J ( θ ) ∂ θ 1 = 1 2 ⋅ 1 m ∑ i = 1 m ( ∂ J i ( θ ) ∂ θ 1 ) = 1 m ∑ i = 1 m ( ( h θ ( x ( i ) ) − y ( i ) ) ⋅ x ( i ) ) \frac{\partial J(\theta )}{\partial \theta _{1}} = \frac{1}{2} \cdot \frac{1}{m}\sum_{i=1}^{m}(\frac{\partial J_{i}(\theta )}{\partial \theta _{1}}) = \frac{1}{m}\sum_{i=1}^{m}((h_{\theta }(x^{(i)})-y^{(i)}) \cdot x^{(i)}) ∂θ1∂J(θ)=21⋅m1i=1∑m(∂θ1∂Ji(θ))=m1i=1∑m((hθ(x(i))−y(i))⋅x(i))
这便是原
J
(
θ
)
J(\theta)
J(θ) 对
θ
0
,
θ
1
{\theta _{0}},{\theta _{1}}
θ0,θ1 求偏导的过程,直观的理解是,对于
J
(
θ
)
J(\theta)
J(θ) 上的某点
(
θ
0
′
,
θ
1
′
)
({\theta _{0}}',{\theta _{1}}')
(θ0′,θ1′) ,该点下降的梯度是每个样本下降梯度和的平均。正是由于批量梯度下降是对所有样本和的平均,所以就平均掉了样本中噪音的梯度,使得
J
(
θ
)
J(\theta)
J(θ) 关于迭代次数的函数图像不会上升,如下图所示:
而对于mini-batch梯度下降,因为噪声或者说比较差的样本不可避免的存在,所以会有很多波动,但对于一个比较好的数据集,质量好的样本仍然占大多数,整体而言,数据揭示着同一种规律,所以图像的整体趋势是下降的,如下图所示:
如果从等高线上看batch、mini-batch和SGD(Stochastic Gradient Descent,随机梯度下降),将会是下面这样的。其中SGD的波动最大,梯度下降的方向甚至还会反向,是因为SGD对每个样本求得的梯度,都做了一次
θ
{\theta}
θ 的更新,如果某个样本较差,恰好给你指的方向不对,那么梯度的方向就有可能反向了,也正是因为这个原因,SGD永远不会收敛,而是会一直在最小值附近波动,为了解决这个问题,可以慢慢减小学习率,即学习率衰减(Learning rate decay)。
绘图参考
https://blog.csdn.net/ygdxt/article/details/86618606
https://blog.csdn.net/Eddy_zheng/article/details/48713449
最后三张图来自吴恩达老师的深度学习课程
前5张图的代码:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
fig = plt.figure()
ax = Axes3D(fig)
X = np.arange(-4, 4, 0.25)
Y = np.arange(-4, 4, 0.25)
X, Y = np.meshgrid(X, Y)
#图5
R = (X+1)**2 + (Y+1)**2
ax.plot_surface(X, Y, R, rstride=1, cstride=1, cmap = plt.get_cmap('rainbow'))
ax.contour(X, Y, R, zdir = 'z', offset = -2, cmap = plt.get_cmap('rainbow'))
plt.show()
'''
#图1
R = X**2 + Y**2
ax.plot_surface(X, Y, R, rstride=1, cstride=1, cmap=plt.cm.CMRmap)
plt.show()
#图2
Z = X**2 + (Y+1)**2
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=plt.cm.Spectral)
plt.show()
#图3
G = (X+1)**2 + Y**2
ax.plot_surface(X, Y, G, rstride=1, cstride=1, cmap=cm.coolwarm)
plt.show()
'''
使用梯度下降法求 y=(x-2)^2 的极值点:
public class GradientDescend {
/**
* 使用梯度下降法求 y=(x-2)^2 的极值点
* 初始化时 x=0
* 梯度为 y' = 2 * x - 4
* 学习率为0.01,迭代1000次的结果:iter=999, x=1.9999999965653725, y=1.1796665866756357E-17
*/
public static void main(String[] args) {
double x = 0, y = Math.pow(x - 2, 2); // y=(x-2)^2
for (int i = 0; i < 1000 && y != 0; i++) {
System.out.println("iter=" + i +", x=" + x + ", y=" + y);
double grad = 2 * x - 4;
x = x - grad * 0.01; //学习率为0.01
y = Math.pow(x - 2, 2);
}
}
}