mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4

梯度下降算法概述

DL 随便写写 搞笑

· 技术

梯度下降算法概述

一、两个老方法及其弊端

观察法

已经是老古董了,再无话说。

再无话说

分治法

分治法缺陷明显:可能错过最优点;一旦权重数量级完全变大,如AlexNet(500万级),会导致划分搜索失效。

二、DL所采用的——梯度下降算法

实际上是用梯度下降算法。

Gradient:∂cost∂ω\frac{\partial cost}{\partial \omega}

Update:w=w−(α∂cost∂ω)w = w - (\alpha \frac{\partial cost}{\partial \omega})

可以理解为是函数曲线求导数的正负号,当为负的时候,下降最猛。每次迭代就向着下降最快的地方狂奔。

算法设计思想:贪心。(梯度下降算法同贪心算法,得到的数据并非是全局最优)

(非凸函数的最优点只是局部最优,梯度下降算法基本求得的就是局部最优)

那么为什么DL/神经网络会采用求局部最优呢?实际上深度神经网络的目标函数内很难陷入局部最优点。只有在鞍点时,梯度为0,无局部最优点。在用梯度下降算法进行梯度优化时,如果到达平缓区域,将无法进行优化更新(陷入鞍点)

所以结合损失函数和梯度下降算法,如下Derivative:

∂cost(ω)∂ω=∂∂ω1N∑n=1N(xn⋅ω−yn)2=1N∑n=1N∂∂ω(xn⋅ω−yn)2=1N∑n=1N2⋅(xn⋅ω−yn)∂(xn⋅ω−yn)∂ω=1N∑n=1N2⋅xn⋅(xn⋅ω−yn)\begin{aligned} \frac{\partial cost(\omega)}{\partial \omega} &= \frac{\partial}{\partial \omega} \frac{1}{N} \sum_{n=1}^{N} (x_n \cdot \omega - y_n)^2 \\ &= \frac{1}{N} \sum_{n=1}^{N} \frac{\partial}{\partial \omega} (x_n \cdot \omega - y_n)^2 \\ &= \frac{1}{N} \sum_{n=1}^{N} 2 \cdot (x_n \cdot \omega - y_n) \frac{\partial (x_n \cdot \omega - y_n)}{\partial \omega} \\ &= \frac{1}{N} \sum_{n=1}^{N} 2 \cdot x_n \cdot (x_n \cdot \omega - y_n) \end{aligned}

其中 y^=ω⋅x\hat{y} = \omega \cdot x ,最后得到了机器学习中经典的梯度下降(Gradient Descent)更新公式:

ω=ω−α1N∑n=1N2⋅xn⋅(xn⋅ω−yn)\omega = \omega - \alpha \frac{1}{N} \sum_{n=1}^{N} 2 \cdot x_n \cdot (x_n \cdot \omega - y_n)

三、具体代码实现

import numpy as np
import matplotlib.pyplot as plt
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
w = 1.0 ### 初始权重
epoch_list = []
loss_list = []
def forward(x):##前馈函数
return x * w
def cost(xs, ys):
cost = 0
for x, y in zip(xs, ys):
y_pred = forward(x)
cost += (y_pred - y) ** 2
return cost / len(xs)
def gradient(xs, ys):###求算梯度
grad = 0
for x, y in zip(xs, ys):
grad += 2 * x * (x * w - y)
return grad / len(xs)
print('Predict (before training)', 4, forward(4))
for epoch in range(100):###训练过程:100轮训练
cost_val = cost(x_data, y_data)###算平均成本
grad_val = gradient(x_data, y_data)###求梯度
w -= 0.01 * grad_val
epoch_list.append(epoch)###为了绘图写的
loss_list.append(cost_val)
print('Epoch:', epoch, 'w=', w, 'loss=', cost_val)
print('Predict (after training)', 4, forward(4))
plt.plot(epoch_list, loss_list) ### x轴是轮数,y轴是损失值
plt.ylabel('Cost') ### 加上引号,变成字符串
plt.xlabel('Epoch') ### 加上引号,变成字符串
plt.show()

输出结果:

Predict (before training) 4 4.0
Epoch: 0 w= 1.0933333333333333 loss= 4.666666666666667
Epoch: 1 w= 1.1779555555555554 loss= 3.8362074074074086
Epoch: 2 w= 1.2546797037037036 loss= 3.1535329869958857
Epoch: 3 w= 1.3242429313580246 loss= 2.592344272332262
Epoch: 4 w= 1.3873135910979424 loss= 2.1310222071581117
......
Epoch: 96 w= 1.9999254544053418 loss= 3.154680994333735e-08
Epoch: 97 w= 1.9999324119941766 loss= 2.593287985380858e-08
Epoch: 98 w= 1.9999387202080534 loss= 2.131797981222471e-08
Epoch: 99 w= 1.9999444396553017 loss= 1.752432687141379e-08
Predict (after training) 4 7.999777758621207

但是以后的深度学习下降曲线难免是不稳定下降的(曲线刺刺的),所以可以来做个加权均值使曲线平滑。

如果学习率太大,也有可能梯度不降反升。

四、随机梯度下降算法

Stochastic Gradient Descent: w=w−(α∂loss∂ω)w = w - (\alpha \frac{\partial loss}{\partial \omega})

拿单个样本的损失对权重求导,由单个样本实现跨越鞍点前进。

以下是SGD代码,相较于批量梯度下降代码进行了更新:

x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
w = 1.0
def forward(x):
return x * w
def loss(x, y):###以前是cost
y_pred = forward(x)
return (y_pred - y) ** 2
def gradient(x, y):###以前是求和,现在是单个求
return 2 * x * (x * w - y)
print('Predict (before training)', 4, forward(4))
for epoch in range(100):
for x, y in zip(x_data, y_data):
grad = gradient(x, y)###对每一个样本求梯度,进行更新
w = w - 0.01 * grad
print("\tgrad: ", x, y, grad)
l = loss(x, y)
print("progress:", epoch, "w=", w, "loss=", l)
print('Predict (after training)', 4, forward(4))
注意:但是在真正的DL里,在计算梯度时,用批量梯度下降算法可并行,但是用SGD无法并行,时间效率低下。最后会取折中——Batch——批量的随机梯度下降。(正式称为Mini—Batch,但由于现在论文中Batch居多,于是都成为Batch了)

版权声明

本文采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处。

显示设置
主题色相
壁纸模式
樱花粒子