CS231n学习笔记七

独自空忆成欢 提交于 2020-01-18 06:15:01

更好的优化方法

前面随机梯度法,当损失函数沿一个方向改变很快而沿另一个方向改变很慢时,此时更新方向会很曲折,收敛速度很慢。而且更新过程可能会停在损失函数的局部最小值点或者鞍点,一般在维度低的时候更可能停在局部最小值处,维度高的时候停在鞍点处的可能性更大。

带动量的梯度法

从物理的角度看:随机的初始化参数相当于在某个位置初始速度为零的粒子。优化过程可以看作是模拟参数向量(即粒子)在山坡上滚动的过程,当粒子到达局部最小值点或者鞍点时由于还带有速度,会继续更新

  1. 第一种表示方式:

vt+1=ρvtαf(xt)xt+1=xt+vt v_{t+1}=\rho v_t-\alpha \nabla f(x_t)\\ x_{t+1}=x_t+v_t

  1. 第二种表示方式:

vt+1=ρvt+f(xt)xt+1=xtαvt v_{t+1}=\rho v_t+\nabla f(x_t)\\ x_{t+1}=x_t-\alpha v_t

vv一般初始化为0,ρ\rho相当于摩擦系数,这样粒子最后肯定是能停下来的。在交叉验证时,ρ\rho通常设置为[0.5、0.9、0.95、0.99]等值。优化有时可以从动量中获益,在学习的后期阶段动量会增加。一个典型的设置是开始时动量约为0.5,然后在多个周期内将增加到0.99左右。

Nesterov 动量

vt+1=ρvtαf(xt+ρvt)xt+1=xt+vt+1 v_{t+1}=\rho v_t-\alpha \nabla f(x_t+\rho v_t)\\ x_{t+1}=x_t+v_{t+1}\\

x~t=xt+ρvt\tilde{x}_t=x_t+\rho v_t,上述式子可写成
vt+1=ρvtαf(x~t)x~t+1=x~tρvt+(1+ρ)vt+1=x~t+vt+1+ρ(vt+1vt) v_{t+1}=\rho v_t-\alpha \nabla f(\tilde{x}_t)\\ \tilde{x}_{t+1}=\tilde{x}_t-\rho v_t+(1+\rho)v_{t+1}\\ \quad\quad\quad=\tilde{x}_t+v_{t+1}+\rho (v_{t+1}-v_t)

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)。
  • 指数递减:α=α0ekt\alpha=\alpha_0e^{-kt}α0,k\alpha_0,k是超参数,tt是迭代步数或epoch
  • α=α0/(1+kt)\alpha=\alpha_0/(1+kt)

实际中,step decay通常效果会好一点。

二阶优化方法

x=H1f(x)x -= H^{-1}\nabla f(x)

然而H储存需要O(n2)O(n^2)空间,求H1H^{-1}需要O(n3)O(n^3)时间,会用拟牛顿法(BFGS/L-BFGS),但是不能很好的转移到小批量设置(随机处理)中。

实际中:

  1. Adam是一个很好的方法,使用固定的学习速率效果就很好
  2. SGD+动量需要通过调整学习速率来获得比Adam更好的效果
  3. 如果可以承担全批量的话可以使用L-BFGS

提高单一模型效果—正则化

前面学习了在损失函数中加入正则项,如L1,L2L_1,L_2正则。下面学习一些新的正则化方式。

**通用思想:**在训练时增加噪声,测试时,边缘化噪声。

**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
    
    # 反向传播
    # 参数更新

训练时,y=fW(x,z)y=f_W(x,z)zz是随机变量,在测试的时候想要消除随机性,y=f(x)=Ez[f(x,z)]=p(z)f(x,z)dzy=f(x)=E_z[f(x,z)]=\int p(z)f(x,z)dz,但是这个积分很难计算,因此计算近似的值。

对于单个神经元aa,测试的时候,E[a]=w1x+w2yE[a]=w_1x+w_2y

p=0.5,训练的时候
KaTeX parse error: No such environment: align at position 8: \begin{̲a̲l̲i̲g̲n̲}̲ E[a]&=\frac{1}…
也就是测试时需要乘上pp

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

也可以在训练的时候除以pp,测试的时候不用乘以pp了。

U1 = (np.random.rand(*H1.shape) < p) / p

**数据增强:**改变数据,如翻转或旋转

​ 1. 在训练时随机裁剪或放缩数据

**DropConnect:**在前向传播时,一组随机的权值被设置为0。

颜色抖动:

1. 对图像的RGB通道使用PCA
2. 沿着主成分方向随机选取颜色偏移
3. 对训练图片的像素加上该偏移

**随机深度网络:**随机去掉某些层,不常用

**部分最大池化:**随机选取池化区域,不常用

迁移学习

有时候过拟合是因为数据量小,迁移学习是一种解决办法

步骤:

预训练:使用大数据集合(与模型数据具有共同的特征)训练网络

训练:冻结除了最后一层的所有层,然后训练小数据集合,如果数据足够多也可以使用小学习率微调整个网络。

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