Mxnet (25): 优化算法

我只是一个虾纸丫 提交于 2020-10-02 08:36:17

对于深度学习问题,通常是先定义损失函数,获得损失之后在通过优化函数尽量减小损失,大多数的优化算法都是涉及最小化。要最大化也很简单只需要在目标上取反即可。

1 优化和估算

优化和深度学习本质上目标是不同的。优化的目的是最小化损失,而深度学习是根据提供的数据找到最佳模型。训练误差和泛化误差通常是不同的:优化算法的目标是损失函数,因此其优化的目的是减少训练误差。而深度学习的目的是减少泛化误差。为了实现后者除了优化函数还需要注意过拟合问题。

from d2l import mxnet as d2l
from mxnet import np, npx
import plotly.express as px
import plotly.graph_objs as go
import pandas as pd
npx.set_np()

这里定义两个函数, 期望函数 f f f 以及经验函数 g g g。这里 g g g 不如 f f f平滑因为我们只有有限的数据。

def f(x):
    return x*np.cos(np.pi*x)

def g(x):
    return f(x) + 0.2 * np.cos(5*np.pi*x)

训练误差的最小值和预测误差的最小值不在一个同一个位置。

x = np.arange(0.5, 1.5, 0.01)
df = pd.DataFrame([f(x).tolist(), g(x).tolist()], index=['expected', 'empirical'], columns=x.tolist()).T

def annotations_set():
    return dict(
            xref="x",
            yref="y",
            showarrow=True,
            arrowhead=2,
            arrowwidth=1.5,
            arrowcolor="#636363",
            bordercolor="#c7c7c7",
            borderwidth=2,
            bgcolor="#ff7f0e"
)

fig = px.line(df, width=600, height=380, labels={
   
   'index':'x', 'value': 'rish'})
fig.add_annotation(x=1.1, y=-1.05, text="expected risk", ax=10, ay=-80)
fig.add_annotation( x=1, y=-1.2, text="empirical risk", ax=-90, ay=-20)
fig.update_annotations(annotations_set())
fig.show()

在这里插入图片描述

2 深度学习中的优化挑战

这里主要研究优化算法,因此关注点是对目标函数优化的性能而不是神经网络的泛化误差。大多数的目标函数很复杂,没有解析解。

优化有许多挑战点:

  • 局部最小
  • 鞍点
  • 梯度消失

2.1 局部最小值

对于目标函数 f ( x ) f(x) f(x),如果 f ( x ) f(x) f(x) x x x 的值小于在它附近的点的 f ( x ) f(x) f(x)值,那么 f ( x ) f(x) f(x) 为局部最小值。如果 f ( x ) f(x) f(x) x x x的值是在整个定义域中最小的值,它为 f ( x ) f(x) f(x) 的全局最小值。

用下面的函数距离,理解全局最小值和局部最小值:

f ( x ) = x ⋅ cos ( π x )  for  − 1.0 ≤ x ≤ 2.0 f(x) = x \cdot \text{cos}(\pi x) \text{ for } -1.0 \leq x \leq 2.0 f(x)=xcos(πx) for 1.0x2.0

使用代码演示

x = np.arange(-1.0, 2.0, 0.01)
fig = px.line(pd.DataFrame([f(x).tolist()], index=['f(x)'], columns=x.tolist()).T ,  width=600, height=380, labels = {
   
   'index': 'x', 'value': 'f(x)'})
fig.add_annotation(x=1.1, y=-0.95, text="global minimum", ax=10, ay=-80)
fig.add_annotation( x=-0.3, y=-0.25, text="local minimum", ax=10, ay=40)
fig.update_annotations(annotations_set())
fig.show()

在这里插入图片描述

深度学习模型的目标函数通常具有许多个局部最小值。当优化的数值接近局部最优的时候,梯度变为0,表示最终迭代获取的数值就是局部最优解,而不是全局最优。随机梯度下降就是为了解决这个问题, 迷你批上的自然变化能够使参数偏离局部最小值。

2.2 鞍点

除了局部最小值外,鞍点是梯度消失的另一个原因。鞍点会使函数梯度消失,但是既不是全局的不是局部的。举个例子函数 f ( x ) = x 3 f(x) = x^3 f(x)=x3. 其一阶和二阶导数在0处为0。0处既不是局部最优也不是全局最优,但是优化还是会停止。

在这里插入图片描述

高维度的数据中鞍点更加隐藏。例如 f ( x , y ) = x 2 − y 2 f(x, y) = x^2 - y^2 f(x,y)=x2y2。它在 ( 0 , 0 ) (0, 0) (0,0) 有一个鞍点。对于 x x x来说它是最大的 y y y值,它看起来像一个马鞍,所以称为鞍点。

x, y = np.meshgrid(np.linspace(-1.0, 1.0, 101), np.linspace(-1.0, 1.0, 101))
z = x**2 - y**2

fig = go.Figure(data = go.Surface(z=z.asnumpy(), showscale=False, colorscale='IceFire'))
fig.update_layout(width = 600, height=580)
fig.add_annotation(x=0, y=0.3, text="saddle point", ax=30, ay=-60)
fig.update_annotations(annotations_set())
fig.show()

在这里插入图片描述

假设输入函数的是一个k维向量,输出位标量,因此其Hessian矩阵将具有 k k k 特征值。梯度为0时,函数的解可以为局部最小,局部最大和鞍点三种情况:

  • 当Hessian矩阵的特征值在零梯度位置都为正时,该函数有一个局部最小值
  • 当Hessian矩阵的特征值在零梯度位置都为负时,该函数有一个局部最大值
  • 当Hessian矩阵的特征值在零梯度位置有正有负,该函数有一个鞍点

简而言之,凸函数是那些Hessian特征值从不为负的函数。

2.3 梯度消失

可能遇到的最隐蔽的问题是梯度消失问题。例如,我们要最小化功能 f ( x ) = tanh ⁡ ( x ) f(x) = \tanh(x) f(x)=tanh(x) 并且以 x = 4 x = 4 x=4开始。 持矢 f f f接近为0。进一步求导 f ′ ( x ) = 1 − tanh ⁡ 2 ( x ) f'(x) = 1 - \tanh^2(x) f(x)=1tanh2(x) 其值为 f ′ ( 4 ) = 0.0013 f'(4) = 0.0013 f(4)=0.0013。因此优化起初进展会很慢。这也是在使用 ReLU激活函数之前训练深度学习模型比较棘手的问题。

x = np.arange(-2.0, 5.0, 0.01)
fig = px.line(pd.DataFrame([np.tanh(x).tolist()], index=['f(x)'], columns=x.tolist()).T ,  width=600, height=380, labels = {
   
   'index': 'x', 'value': 'f(x)'})
fig.add_annotation(x=4, y=1, text="vanishing gradient", ax=-10, ay=80)
fig.update_annotations(annotations_set())
fig.show()

在这里插入图片描述

3. 参考

https://d2l.ai/chapter_optimization/optimization-intro.html

4. 代码

github

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!