更好的优化方法
前面随机梯度法,当损失函数沿一个方向改变很快而沿另一个方向改变很慢时,此时更新方向会很曲折,收敛速度很慢。而且更新过程可能会停在损失函数的局部最小值点或者鞍点,一般在维度低的时候更可能停在局部最小值处,维度高的时候停在鞍点处的可能性更大。
带动量的梯度法
从物理的角度看:随机的初始化参数相当于在某个位置初始速度为零的粒子。优化过程可以看作是模拟参数向量(即粒子)在山坡上滚动的过程,当粒子到达局部最小值点或者鞍点时由于还带有速度,会继续更新
- 第一种表示方式:
- 第二种表示方式:
一般初始化为0,相当于摩擦系数,这样粒子最后肯定是能停下来的。在交叉验证时,通常设置为[0.5、0.9、0.95、0.99]等值。优化有时可以从动量中获益,在学习的后期阶段动量会增加。一个典型的设置是开始时动量约为0.5,然后在多个周期内将增加到0.99左右。
Nesterov 动量
令,上述式子可写成
AdaGrad
grad_squared = 0
while True:
dx = compute_gradient(x)
grad_squared += dx * dx
x -= learning_rate * dx / (np.sqrt(grad_squared) + 1e-7)
沿着“陡峭”方向的进展受到阻碍;沿着“平坦”方向的进展加快了;但随着时间的增加,步长会趋于零。进一步改进有RMSProp方法。
RMSProp
grad_squared = 0
while True:
dx = compute_gradient(x)
grad_squared = decay_rate * grad_squared + (1- decay_rate) * dx * dx
x -= learning_rate * dx / (np.sqrt(grad_squared) + 1e-7)
Adam
有点像是动量和RMSProp的结合
first_moment = 0
second_moment = 0
for t in range(1, num_iterations):
dx = compute_gradient(x)
first_moment = beta1 * first_moment + (1 - beta1) * dx
second_moment = beta2 * second_moment + (1 - beta2) * dx * dx
first_unbias = first_moment / (1- beta1 ** t)
second_unbias = second_moment / (1- beta2 ** t)
x -= learning_rate * first_unbias / (np.sqrt(second_unbias) + 1e-7)
对于许多模型来说,beta1 = 0.9, beta2 = 0.999, learning_rate = 1e-3或5e-4是一个很好的选择。
学习速率的选取
一般是用固定的训练,观察loss函数,再考虑在什么时候减小学习速率
- **step decay:**每隔几个epoch就把学习速率降低一些。典型的可能是每5个周期减少一半的学习率,或者每20个周期减少0.1。这些在很大程度上取决于问题的类型和模型。在实践中可能看到的一种启发式方法是,在使用固定的学习率进行训练时观察验证错误,并在验证误差停止改进时将学习率降低一个常数(例如0.5)。
- 指数递减:,是超参数,是迭代步数或epoch
实际中,step decay通常效果会好一点。
二阶优化方法
然而H储存需要空间,求需要时间,会用拟牛顿法(BFGS/L-BFGS),但是不能很好的转移到小批量设置(随机处理)中。
实际中:
- Adam是一个很好的方法,使用固定的学习速率效果就很好
- SGD+动量需要通过调整学习速率来获得比Adam更好的效果
- 如果可以承担全批量的话可以使用L-BFGS
提高单一模型效果—正则化
前面学习了在损失函数中加入正则项,如正则。下面学习一些新的正则化方式。
**通用思想:**在训练时增加噪声,测试时,边缘化噪声。
**Dropout:**在每一次前向传播时,随机将一些神经元设置为0,也就是激活函数设为0。
p = 0.5
def train_step(X):
H1 = np.maximum(0, np.dot(W1, X) + b1)
U1 = np.random.rand(*H1.shape) < p # 第一次dropout mask
H1 *= U1 # drop
H2 = np.maximum(0, np.dot(W2, H1) + b2)
U2 = np.random.rand(*H2.shape) < p # 第二次dropout mask
H2 *= U2 # drop
out = np.dot(W3, H2) + b3
# 反向传播
# 参数更新
训练时,,是随机变量,在测试的时候想要消除随机性,,但是这个积分很难计算,因此计算近似的值。
对于单个神经元,测试的时候,
p=0.5,训练的时候
KaTeX parse error: No such environment: align at position 8:
\begin{̲a̲l̲i̲g̲n̲}̲
E[a]&=\frac{1}…
也就是测试时需要乘上值
def predict(X):
H1 = np.maximum(0, np.dot(W1, X) + b1) * p
H2 = np.maximum(0, np.dot(W2, H1) + b2) * p
out = np.dot(W3, H2) + b3
也可以在训练的时候除以,测试的时候不用乘以了。
U1 = (np.random.rand(*H1.shape) < p) / p
**数据增强:**改变数据,如翻转或旋转
1. 在训练时随机裁剪或放缩数据
**DropConnect:**在前向传播时,一组随机的权值被设置为0。
颜色抖动:
1. 对图像的RGB通道使用PCA
2. 沿着主成分方向随机选取颜色偏移
3. 对训练图片的像素加上该偏移
**随机深度网络:**随机去掉某些层,不常用
**部分最大池化:**随机选取池化区域,不常用
迁移学习
有时候过拟合是因为数据量小,迁移学习是一种解决办法
步骤:
预训练:使用大数据集合(与模型数据具有共同的特征)训练网络
训练:冻结除了最后一层的所有层,然后训练小数据集合,如果数据足够多也可以使用小学习率微调整个网络。
来源:CSDN
作者:kkklern
链接:https://blog.csdn.net/zll1130/article/details/103793102