1. 优化方法
1. Momentum(冲量)
-
在普通的梯度下降法x += v中,每次x的更新量v为v = - dx * lr,其中dx为目标函数func(x)对x的一阶导数。当使用冲量时,则把每次x的更新量v考虑为本次的梯度下降量- dx * lr与上次x的更新量v乘上一个介于[0, 1]的因子momentum的和,即v = - dx * lr + v * momemtum。
从公式上可看出: -
当本次梯度下降- dx * lr的方向与上次更新量v的方向相同时,上次的更新量能够对本次的搜索起到一个正向加速的作用。
-
当本次梯度下降- dx * lr的方向与上次更新量v的方向相反时,上次的更新量能够对本次的搜索起到一个减速的作用。
2. Adagrad
3. RMSProp
- rmsprop算法不再孤立地更新学习步长,而是联系之前的每一次梯度变化情况,具体如下。
- rmsprop算法给每一个权值一个变量MeanSquare(w,t)用来记录第t次更新步长时前t次的梯度平方的平均值。
- 然后再用第t次的梯度除上前t次的梯度的平方的平均值,得到学习步长的更新比例。
- 根据此比例去得到新的学习步长。如果当前得到的梯度为负,那学习步长就会减小一点点;如果当前得到的梯度为正,那学习步长就会增大一点点。
4. Adam
- Adam优化算法基本上就是将Momentum和RMSprop结合在一起。
- Adam 是一种可以替代传统随机梯度下降过程的一阶优化算法,它能基于训练数据迭代地更新神经网络权重
5. 算法的选择
- 动量法与Nesterov的改进方法着重解决目标函数图像崎岖的问题
- Adagrad与Adadelta主要解决学习率更新的问题
- Adam集中了前述两种做法的主要优点
- 目前为止 Adam 可能是几种算法中综合表现最好的
代码实现
RMSProp
def rmsprop(w, dw, config=None):
if config is None: config = {}
learning_rate = config.get('learning_rate', 1e-2)
decay_rate = config.get('decay_rate', 0.99)
epsilon = config.get('epsilon', 1e-8)
cache = config.get('cache', np.zeros_like(w))
cache = decay_rate * cache + (1 - decay_rate) * dw ** 2
next_w = w - learning_rate * dw / (np.sqrt(cache) + epsilon)
config['cache'] = cache
return next_w, config
Adam
def adam(w, dw, config=None):
"""
config format:
- learning_rate: Scalar learning rate.
- beta1: Decay rate for moving average of first moment of gradient.
- beta2: Decay rate for moving average of second moment of gradient.
- epsilon: Small scalar used for smoothing to avoid dividing by zero.
- m: Moving average of gradient.
- v: Moving average of squared gradient.
- t: Iteration number.
"""
if config is None: config = {}
config.setdefault('learning_rate', 1e-3)
config.setdefault('beta1', 0.9)
config.setdefault('beta2', 0.999)
config.setdefault('epsilon', 1e-8)
config.setdefault('m', np.zeros_like(w))
config.setdefault('v', np.zeros_like(w))
config.setdefault('t', 0)
m = config['m']
v = config['v']
t = config['t'] + 1
beta1 = config['beta1']
beta2 = config['beta2']
epsilon = config['epsilon']
learning_rate = config['learning_rate']
m = beta1 * m + (1 - beta1) * dw
v = beta2 * v + (1 - beta2) * (dw ** 2)
mb = m / (1 - beta1 ** t)
vb = v / (1 - beta2 ** t)
next_w = w - learning_rate * mb / (np.sqrt(vb) + epsilon)
config['m'] = m
config['v'] = v
config['t'] = t
return next_w, config