Loss function
一般将Logistic Loss称之为Cross-entropy Loss,这两者是等价的。Wiki
Softmax Loss可以看作对于模型输出应用Softmax之后,再进行Logistic Loss(计算公式)
sigmoid -> softmax, lossfunction is the same with logistic regression (logistic loss)
随机梯度下降法(Stochastic Gradient Descent) SGD
每次选取minibatch
- 为什么不使用过大(比如全部样本)的batch size:在相同计算量下,即训练样本数不变的情况下,一般来讲,多轮少量样本迭代比少轮大量样本迭代效果好。因为样本达到一定数量后,继续增加样本数量对于梯度估计的精度提升是相当有限的。而同样计算量下的多轮少量迭代,因为参数被迭代更新的次数更多,一般会取得更快速的收敛。、
- 为什么不使用过小(比如1)的batch size:主要是速度方面的考虑,对于现代硬件来讲(如SIMD的CPU,GPU等),batch size太小时难以发挥出硬件的并行加速能力,使得batch size太小时即使相同的计算量也会花费几倍的物理时间,此外每次更新模型需要额外的计算量。其次是性能方面考虑,在相同的训练样本下,每次估计梯度使用非常小的样本(比如batch size是1)未必是性能最好的选择。算法上的解释是单个样本估计的梯度可能误差过大,实际上的训练经验也显示太小的batch size有损性能。
- 为什么要随机一批数据:可以获得更多样的batch,使得模型的泛化性更强,某种程度上相当于做了data augmentation。
随着 batch_size 减少,性能逐渐增强(acc增大)(最后的batch_size为10略有下降除外),速度在batch size较小时显著变慢。
- batch_size增大,模型精确度会下降,但速度会显著提升。
- batch_size变小,物理消耗更多,
- batch size 越小, 相同 epoch 的性能越好, 训练越慢. 另外, 当 batch size 已经足够小时, 继续减小不会有明显的性能提升, 而训练速度会继续显著变慢.
在合理范围内,增大 Batch_Size 有何好处?
内存利用率提高了,大矩阵乘法的并行化效率提高。
- 跑完一次 epoch(全数据集)所需的迭代次数减少,对于相同数据量的处理速度进一步加快。
- 在一定范围内,一般来说 Batch_Size 越大,其确定的下降方向越准,引起训练震荡越小。
盲目增大 Batch_Size 有何坏处?
内存利用率提高了,但是内存容量可能撑不住了。
- 跑完一次 epoch(全数据集)所需的迭代次数减少,要想达到相同的精度,其所花费的时间大大增加了,从而对参数的修正也就显得更加缓慢。
- Batch_Size 增大到一定程度,其确定的下降方向已经基本不再变化。
Learning Rate
过小的learning rate会使得收敛过慢,而且可能使得模型陷入局部最优(local minimum),难以收敛到全局最优。 过大的learning rate在训练后期会使得模型参数变化较为剧烈,性能会停在一个水平上,难以进一步提升。
常用的learning rate调整策略是先大后小。先大后小的策略可以在训练早期较快地往最优解方向收敛同时避免掉陷入局部最优,在训练的后期能够比较精细地调整模型,使得模型越来越接近最优解。
过早的让LR变小对性能没什么改进,最终的收敛性能变差。
CNN
为什么要用CNN:数据比较大的时候fc参数太多。它的思路是限制输入层和隐藏层之间的连接,只允许隐藏层每个神经元和输入层中有限个元素有连接,同时对于连接间的独立性进行了限制,不同的神经元之间需要共享连接参数。
卷积layer
关于conv操作的计算:kernal的厚度就是kernal的数量把?所以kernal的厚度=输出的矩阵的厚度。
kenel的厚度和kernel的个数是相等的,但是每个kernel的通道数应该跟输入Input的通道数相同,但是kernel的通道数又不是厚度,因为厚度是kernel的个数。。(这个定义怎么这么绕。。)
注意:每一个kernel会带有一个Bias b0 和 b1, size=(1*1*1)(此时Input channel = 3, kernel_num = 2, kernel_channel = 3)
思考:在上面这张图上,卷积层有几个神经元?每个神经元对应的是什么:(不知道)
- 两个,每个神经元代表一个kernel,一共两个kernel。(XXXXX!!!)
- 每个kernel的每个点是一个神经元,所以又K*K*c*n_kenel个神经元!因为对于每个神经元代表一种连接,kernel中的每个点都和input的所有的点进行了相同的操作(乘法),所以应该以点为单位而不是kernel??
|
dilation 扩张
Pooling Layer
池化层会不断地减小数据的空间大小,因此参数的数量和计算量会下降,这在一定程度上控制了模型的过拟合。 同时,由于池化的采样是基于临近输入区域进行的,池化层可以一定程度上保证模型对于图像平移抖动有较强的稳定性。 也就是说,输入层轻微的平移不会对输出层的大部分值产生影响. 对于需要精确定位的壬戌需要注意pooling的影响。
在分类task中比较常用因为分类更关心某个feature是否存在,以及和其他特征的相对位置的大概关系。
aver vs max: max is better. 最近由于最大池化在实践中的表现更好,平均池化已经不太常用,除了在分类问题中用于卷积和全连接的衔接处。
特性 | 含义 | 优势 | 假设 |
局部感知 | 每个神经元只和输入中的一个局部区域相关 |
|
图像的空间局域性:一个像素只和其邻近的像素构成概念 |
参数共享 | 每个神经元使用相同的卷积核进行运算 |
|
图像的平移不变性:局部图像的特征和所在图片中的位置没有关系 |
多层卷积 | 多层卷积神经网络级联 | 使得模型有能力表达更大更复杂的概念, 越上面的layer表达的feature越复杂 | 物体的组合性质:大的复杂的物体由小的简单的物体组成,高级的概念由低级的概念组成 |
最大池化 | 将输入的图像划分为若干个矩形区域,对每个子区域输出最大值。 |
|
一个特征的精确位置远不及它的存在以及和其他特征的相对位置的关系重要 |
网络初始化 - Xavier & MSRA
这两种策略希望达到的目的一致的,都是希望保证,每一层输出的方差尽量一致,不要出现指数级上升或者下降的情况。 这样可以保证在前向传播和反向传播时网络中的信息能够更好的流动。
Xavier:
假设:
- 输入和权重参数的各个元素分别独立同分布,且均值为0。
- 激活函数可近似为一个线性函数,且0点处的导数为1
每一层的weight的参数的分布应:Var[w_l] = 1/n_l
n_l为ith layer的输入
MSRA:
假设:
- 权重参数的各个元素分别独立同分布,且均值为0。
- 输入的各个元素分别独立同分布,但均值不一定为0。
- 激活函数为ReLU
每一层的weight的参数的分布应:Var[w_l] = 2/n_l,且平均值=0(正态分布)
可以看到,Xavier方式产生的权重参数的方差为MSRA方法的一半。 文章指出这个差别会导致由前者产生的网络中,每层的输出的方差会随着层数的增加而指数递减,当整个网络层数增加的时候,这个影响会更加明显,导致网络收敛变慢,甚至无法收敛。
- 如果采用均值为零的对称函数(比如tanh),应该采用Xavier策略。
- 如果采用ReLU(均值非零)作为激活函数,应该采用MSRA策略。
- 采用Xavier的话会导致训练收敛变慢,在非常深的网络上可能会无法收敛。
- 如果网络已经使用了Batch Normalize优化,则会大大减小不同初始化策略带来的影响(BN忘记了!!!)
归一化
- 学习更快了
- 避免树脂太大,发生程序数值一处或者丢失精度
- 在计算loss func时候如果某个特征的数值范围太大会导致loss fun被这个特征主导(大多数分类器会计算欧拉距离)。
- 跟BN不是相同的概念!
(备份)如何跑通第一个模型
面对一个全新的任务时,可能会遇到深度神经网络的训练不收敛的情况:loss不下降或者计算过程中浮点数越界,处理这种情况有一些常见的技巧。总体的思路是尽量简化训练,使得网络参数很容易学,即使性能不够优,切忌在跑通第一个模型前就做很多为性能优化服务的、增加训练难度的事项,例如数据增强、网络加宽加深等。
7.1 模型参数选择
尽量找一个已经跑通过的、与当前任务相似的任务,借鉴其模型、超参数。任务相似主要包括:数据规模、训练目标(代价函数)、视觉任务的难度上相近。
- 优先使用复杂度较低的网络,一方面可以排除参数太多学不动的问题(Res-Net在这方面有很大优势,几乎不会学不动),一方面可以加快实验迭代效率。
- 用其他任务学好的模型参数做初始化,可以大大加速收敛,即使任务不同也没关系。
- 先调低learning rate,可以等模型收敛后再把learning rate调高。
7.2 数据集
减小训练集,先在训练集上测试,让模型overfit训练集。
- 确认数据做了random shuffle(特别注意:caffe DataLayer的shuffle是不充分的)。
- 确认数据做了归一化(在使用BN的情况下这一点不太重要),像素的灰度值较大(0-255),容易造成模型参数振荡并越界。
7.3 输出调试信息
在训练流程中显示输入数据,包括图片和label,这是最容易出错的地方。
- 查看每一层模型权重、每一层的输出是否合理,一般的DL工具会提供绝对值均值、方差。
loss层输出一些细化的统计量,例如在分类、检测中,输出每个类别的数据量、平均score等。
Part 3
start: 5:20
CNN的BP
池化层的BP计算与上图中“max操作”类似,当使用max pooling时,池化层只会将高层梯度值传播给最大输入连接;当使用average pooling时,梯度信号会被均分传播给所有输入连接。
卷积层的BP计算与FC层类似,但由于卷积kernel的系数会被多次共享使用,因此在一轮BP中,每个系数会收到多个梯度信号。算法需要将这些信号相加,再根据梯度下降法对参数进行更新
LR调整的方法
1. 手动
- 当training loss不再下降(在固定范围内抖动)时,将LR乘以衰减系数γγ,γγ通常在0.1到0.5之间。
- 缺点:耗时,人工
- 有点:能最优
2. 阶梯指数下降:LR每经过stepstep轮,乘以衰减系数γγ,通常会将 stepstep设得较小,而γγ设得较大,如0.99。
3. 多项式函数下降:
- 会使得LR在较大值停留轮数多,较小值停留轮数少
- 优点:方便,只要调整iter_max一个参数
- 缺点:性能有时不能达到最优
SGD的优化
1. SGD的缺点:
- 收敛慢
- 局部最优和高原处理不好
- 完全不考虑参数自身的因素
2. momentum:相当于对每一步的导数的结果使用指数移动平均,再用W = W - alpha * (指数指数移动平均的dW)
3. NAG没看懂
4. Adagrad:对于经常被更新的参数,Adagrad会做较小的更新,对于较少被更新的参数,Adagrad会做较大的更新。
5. RMSProp: RMS:平均方根,解决Adagrad的梯度消失问题
6. Adadelta:
- RMSProp中的更新项是常数刚量
- 而Adadelta对此进行了改进,改为了参数刚量
- 全局学习率alpha完全不存在了,便车过年了参数的RMS。
- 同样可以解决Adagrad的梯度消失问题
- 由于EMA使用0初始化,会在训练早期使得统计矩的估计明显偏向于0。所以有了Adam
- 收敛非常快
- 是DL的首选方法
- 另外,比RMSProp还多了一步调整:Sdw /= (1 - beta^t)。t是当前iteration的idx。
- RMSProp, Adam,Adadelta 收敛比较快
防止过拟合的方法
1. Early Stopping
2. 添加正则项/Weight-decay
- Weight-decay: 在lossfunc上添加的正则项为a*L2 norm时。是L2-penalty
- 方法:增加penalty使参数范围不会太大
- 也可以设置参数的hard limit取值
- 不包括bias,因为bias参数少,加上了反而欠拟合
- 不同loss penalty
- 不同网络结构
- 不同优化算法
4. Data augmentation(数据增强)
5. 增加噪声
- 可以在不同layer增加噪声,更加robust
- 可以在原始数据增加
- 可以在参数上增加(RNN)
6. Dropout
- 可以当作每个dropout是不同的structure
- 可以当作相同样本在不同dropout中是不同的样本-data augmentation
BN
1. 计算过程:
- 对于每一个batch的在layer的output:(处理还没有激活的数据(这个不确定)实际多在激活之后BN)运行和归一化一样的操作(只限于当前batch计算mean & var)
2. 好处:
- 数据均匀,收敛更快
- 输入的分布都是一样的了
- 网络权重的初始化更容易了
- 能起到正则华的作用,可以replace droopout
3. Nwork-in-Network(这里了解的比较少)
- Inception模块:使用了1*1 conv压缩了特征维度
- 可以增加模型的表达能力
- 使用不同的kernel应用在相同的input上面,从相同的input里面抽取不同的尺度的特征。
- 好处:
- 模型参数和计算量小
- Inception模块的表达能力好,有多个分支并行刻画数据分布,能用较少的参数和计算学习到有效的特征
- 简单的CNN只能通过多层串行的低效办法。
ResNet
1. 为什么越deep模型效果反而不好:
- 深层网络面临的优化问题难度更大???