一、Gradient Descent(梯度下降算法)
(1)、Batch Gradient descent(BGD, 指计算梯度时用的是全部样本的梯度的均值)
Batch Gradient descent 是一种求最小局部变量的一阶迭代优化算法。利用gradient descent来求一个函数的最小值,我们每一步都在当前点加上一个负梯度的倍数。如果我们采用的是正梯度,则计算的是函数的局部最大值。这就像我们要从山上的某个点下山,如何最快的到达山底,我们的方法就是在当前点选择下山的最陡的方向走,这就是梯度下降。
给定一个多变量函数 F ( x ) F(x) F(x),同时在点 a a a处可微,则从点 a a a处下降最快的方向就是 − ∇ F ( a ) -\nabla F(a) −∇F(a),表示为如下形式:
a n + 1 = a n − γ ∇ F ( a n ) a_{n + 1} = a_{n} - \gamma \nabla F(a_n) an+1=an−γ∇F(an)
对 γ ∈ R + \gamma \in R_+ γ∈R+,且足够下,有 F ( a n ) ≥ F ( a n + 1 ) F(a_n) \geq F(a_{n + 1}) F(an)≥F(an+1).
- python_code.py
x = 6
step_size = 0.01 # 每次移动的步长
step_tolerance = 0.00001 # 停止条件
max_iterations = 10000 # 运行最大进行的迭代次数
# Derivate function f'(x)
df = lambda x: 4 * x ** 3 - 9 * x ** 2
for j in range(max_iterations):
step = step_size * df(x)
x -= step
if abs(step) < step_tolerance:
break
print('Minimum:', x) # 2.2499646074278457
print('Exact:', 9/4) # 2.25
print('Iterations:',j) # 69
不管是这里的BGD还是后面的SGD、MBGD,只要确定了损失函数,则其梯度公式也就确定了,所不同的是这个梯度的值,这是什么意思呢?
给个例子:
假设有三个数据[3, 5, 9, 2], 确定的loss function为 J ( x ) = 10 ∗ x 5 + 8 ∗ x 2 J(x) = 10 *x^5 + 8 * x^2 J(x)=10∗x5+8∗x2,其确定的梯度公式为 ∇ J ( x ) = 50 ∗ x 4 + 16 ∗ x \nabla J(x) = 50 * x^4 + 16* x ∇J(x)=50∗x4+16∗x,我们将 ∇ J ( x ) \nabla J(x) ∇J(x)的带入数据后算出来的值记为params_grad。
对于BGD,其算的是所有样本的均值,即 p a r a m s _ g r a d = ∇ J ( 3 ) + ∇ J ( 5 ) + ∇ J ( 9 ) + ∇ J ( 2 ) 4 = 91113.5 params\_grad = \frac{\nabla J(3) + \nabla J(5) +\nabla J(9) +\nabla J(2)}{4} = 91113.5 params_grad=4∇J(3)+∇J(5)+∇J(9)+∇J(2)=91113.5;
对于SGD,其算的某个样本的值(例如取x = 3),即
p a r a m s _ g r a d = ∇ J ( 3 ) = 4098 params\_grad = \nabla J(3) = 4098 params_grad=∇J(3)=4098
而对MBGD,其算的某些样本的的均值(例如取x = 3, 5),即
p a r a m s _ g r a d = ∇ J ( 3 ) + ∇ J ( 5 ) 2 = 17714.0 params\_grad = \frac{\nabla J(3) + \nabla J(5)}{2} = 17714.0 params_grad=2∇J(3)+∇J(5)=17714.0
所以这给出多个训练样本的时候的部分代码:
for i in range(nb_epochs):
params_grad = evaluate_gradient(loss_function, data, params)
params = params - learning_rate * params_grad
BGD对于凸函数能够收敛到全局最优,但对于非凸函数,能收敛到局部最优。
(2)、Stochastic Gradient Descent(SGD,随机梯度下降)
SGD使用一个训练样本
(
x
(
i
)
,
y
(
i
)
(x^{(i)}, y^{(i)}
(x(i),y(i)来更新参数的。
a
n
+
1
=
a
n
−
γ
∇
F
(
a
n
,
x
(
i
)
,
y
(
i
)
)
a_{n + 1} = a_{n} - \gamma \nabla F(a_n, x^{(i)}, y^{(i)})
an+1=an−γ∇F(an,x(i),y(i))
相比于BGD,SGD有可能能够跳出当前的局部最优点,然后去获得一个很好的局部最优点;但是SGD也容易困于局部最优,并且在某些情况下可能被困于鞍点。
for i in range(nb_epochs):
np.random.shuffle(data)
for example in data:
params_grad = evaluate_gradient(loss_function, example, params)
params = params - learning_rate * params_grad
(3)、Mini-Batch Gradient Descent
MBGD使用一部分训练样本
(
x
(
i
:
i
+
n
)
,
y
(
i
:
i
+
n
)
(x^{(i: i + n)}, y^{(i: i + n)}
(x(i:i+n),y(i:i+n)来更新参数的。
a
n
+
1
=
a
n
−
γ
∇
F
(
a
n
,
x
(
i
+
n
)
,
y
(
i
+
n
)
)
a_{n + 1} = a_{n} - \gamma \nabla F(a_n, x^{(i + n)}, y^{(i + n)})
an+1=an−γ∇F(an,x(i+n),y(i+n))
有如下优点:
1)减少了参数更新的方差,使得更加稳定收敛;
2)通常的mini-batch 的大小为50~256;
for i in range(nb_epochs):
np.random.shuffle(data)
for batch in get_batches(data, batch_size = 50):
params_grad = evaluate_gradient(loss_function, batch, params)
params = params - learning_rate * params_grad