cs231n 学习笔记 第七课

复习:

(1)为什么要进行归一化:使分类函数的裕度更大,对数据扰动的容忍程度更大

(2)过拟合的解决方法:添加正则化项

(3)参数调整规则:一般最先调整学习率(最敏感),调整到比最优值略小

更有效的优化:

(1)随机梯度下降的问题:

a.一些函数的梯度方向并不是指向其最小值的,此时使用梯度下降就会出现“之”字型曲线 。e.g.椭圆形等高线

b.会卡在损失函数的局部极小或鞍点上。

ps:一维上,局部极小较明显,鞍点显得没那么重要;但是高维时,局部极小出现的很少,但是鞍点影响的更频繁

(2)更好的优化算法——动量

SGD: x_{t+1} = x_t - \alpha \nabla f(x_t)

SGD+Momentum: v_{t+1} = \rho v_t + \nabla f(x_t)  x_{t+1} = x_t - \alpha v_{t+1} 一般ρ=0.9/0.99,让其有了惯性~

Nesterov\: Momentum: v_{t+1} = \rho v_t-\alpha \nabla f(x_t+\rho v_t)\: x_{t+1} = x_t + v_{t+1}

#Nesterov Momentum
dx = compute_gradient(x)
old_v = v
v = rho * v - learning_rate * dx
x += -rho * old_v + (1 + rho) * v

先沿着速度方向前进,得到对应点的梯度,然后返回起始点,利用刚才求得的梯度再计算,进行真正的前进

初始化:最初速度设置为0

ps:带动量的情况下很容易就会越过极小值点——缺点

(3)AdaGrad

计算每一步梯度的平方,并累加求和,并让参数更新的时候除以这个平方和的平方根。

grad_squared = 0
while True:
    dx = compute_gradient(x)
    grad_squared += dx * dx
    x -= learning_rate * dx / (np.sqrt(grad_squared) + 1e-7) #添加1e-7防止除0

当多维情况下,各个方向梯度大小不一致,通过AdaGrad来平衡梯度前进的方向,但是随着迭代次数增加,步长会越来越小,也会很容易被局部极小困住

(4)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)

衰减率通常为0.9/0.99, 用以解决随着迭代次数增加而使步长减小的问题

(5)Adam(almost):Momentum 和 RMSProp的结合:

first_moment = 0  #第一动量
second_moment = 0 #第二动量
while True:
    dx = compute_gradient(x)
    first_moment = beta1 * first_moment +(1 - beta1) * dx #Momentum
    second_moment = beta2 * second_moment + (1 - beta2) * dx * dx #RMSProp
    x -= learning_rate * first_moment / (np.sqrt(second_moment) + 1e-7))

缺点:最初时候第一、二动量都很小,有可能会使初始的步长变得很大

Adam(full)

first_moment = 0  #第一动量
second_moment = 0 #第二动量
for t in range(num_iterations):
    dx = compute_gradient(x)
    first_moment = beta1 * first_moment +(1 - beta1) * dx #Momentum
    second_moment = beta2 * second_moment + (1 - beta2) * dx * dx #RMSProp
    first_unbias = first_moment / (1 - beta1 ** t) #Bias correction
    second_unbias = second_moment/ (1 - beta2 ** t)    
    x -= learning_rate * first_unbias / (np.sqrt(second_unbias) + 1e-7))

解决步长问题:当t很小的时候,对应初始状态,第一、二动量就会除以一个很大的数;随着t的增大,unbias 逐渐趋于moment

Adam是一个相当棒的算法,初值可以考虑设置为:beta1 = 0.9, beta2 = 0.999, learning_rate = 1e-3 或 5e-4

(6)学习率衰减:

最初设置个较大的学习率,然后随着迭代次数增加而不断衰减

ps:一些论文中损失函数的曲线会出现几次骤降,可能是由于在拐点处发生了学习率的变化所导致的

pss:学习率衰减通常用于SGD,AdaGrad,但少用于Adam

psss:学习率衰减是一个二阶的超参数,最初往往不适用,而是找到一个不错的学习率,再尝试使用学习率衰减

(7)二阶拟合

之前的梯度下降仅仅用了泰勒的一阶近似,但也可以使用二阶近似(牛顿法)。但是参数量巨大,不太现实

(8)集成学习:训练多个不同模型,结果取平均,大概会提升2%。也不一定需要独立的训练这些模型

(9)正则化:防止过拟合

review:L1, L2正则化

dropout:在进行前向传播时,随机让每一层的神经元置零(实际为激活函数置零,一般在全连接层,有时也用在卷积层)

测试时,不再置零,而是直接将输出乘以置零的概率

一直提升速度的方法:在测试时不再乘以概率,而是在训练的时候,将输出除以置零的概率

原理:训练时给网络加入随机量,通过扰乱网络的方法以防止其过拟合

ps:BN和dropout是相似的,有时不必同时使用

(10)数据增强:给数据中引入随机性:水平翻转,随机裁剪(中心,四个角),色彩抖动(color jitter)(使用较少)

(11)随机深度:随机丢弃深度网络的部分层,但测试时的使用整个层

ps:一般只使用batch normalization,如果发现过拟合之后再加入dropout等其他方法

(12)迁移学习 transfer learning:先找到成熟的网络,在一个较大的数据集上训练(ImageNet), 然后修改输入和输出的全连接层。冻结中间层。

ps:如果是很小的数据集,输入部分只需要修改第一个全连接层即可,其余冻结;而如果是中等数据集,则输入部分可能要多改几层,或者是训练整个网络,但是调低学习率。

pss:目前大部分网络使用到CNN时都是先在ImageNet上预训练好,然后再对网络进行fine tune

你可能感兴趣的:(cs231n)