问题:
实际上,真正的学习过程中,cost(w)不会是一个平滑的曲线。当只要有一个维度时,还可以做线性搜索。但当权重个数为两个或多个时,如 ,此时搜索量剧增。
优化问题
优化问题:求目标函数(cost(w))的权重组合
梯度下降算法(Gradient Descent)
假设在某个损失函数里,模型的损失cost 与 一个权重w 的关系如下图。
权重w 目前在该红点处。此时,如果求出该点的梯度 ,就可以知道该点该往右走还是往左走能使损失函数cost的值达到最小,即梯度为0的点。
更新权重w,其中 为学习率,学习率一般取得较小。此时,通过计算可以得到前进的距离(步长)。
问题
然而,在梯度下降会遇到最优化问题中两个常见的问题:局部最小值和鞍点。
局部最小值
有时我们计算出的损失函数,可能会存在多个局部最小值,此时梯度下降法只是找到其中的一个局部最小值而停止,不能找到全局最优。
我们可以通过取多个不同的初始值执行算法,来选择算是函数最小的初始值。
鞍点
鞍点:函数在此点的梯度为0。此时,导致w没办法进行迭代。
随机梯度下降
实际上,在深度学习中,常用的是随机梯度下降(Stochastic Gradient Descent)。区别在于,不再是计算整个目标函数的损失,而是计算单个样本的损失,以此,引入了随机噪声,即使陷入鞍点,随机噪声可能使 权重w 在更新的过程中跨越鞍点。
代码
梯度下降:
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=[] # 存储数据,方便后期画图
cost_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):
cost_val = cost(x_data, y_data)
grad_val = gradient(x_data, y_data)
w -= 0.01 * grad_val
epoch_list.append(epoch)
cost_list.append(cost_val)
print('Epoch:', epoch, 'w=', w, 'loss=', cost_val)
print('Predict (after training)', 4, forward(4))
# 绘图
plt.plot( epoch_list, cost_list)
plt.ylabel('w')
plt.xlabel('epoch')
plt.show
输出:
随机梯度下降:
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=[]
cost_list = []
# 定义前馈函数
def forward(x):
return x * w
# 损失函数 求单个样本的损失
def loss(x, y):
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)
epoch_list.append(epoch)
cost_list.append(l)
print('progress:', epoch, 'w=', w, 'loss=', 1)
print('Predict (after training)', 4, forward(4))
# 绘图
plt.plot( epoch_list, cost_list)
plt.ylabel('w')
plt.xlabel('epoch')
plt.show
输出: