常见问题总结
深度学习基础常见问题总结
神经网络中1*1卷积有什么作用?
降维,减少计算量;在ResNet模块中,先通过11卷积对通道数进行降通道,再送入33的卷积中,能够有效的减少神经网络的参数量和计算量;
升维;用最少的参数拓宽网络通道,通常在轻量级的网络中会用到,经过深度可分离卷积后,使用1*1卷积核增加通道的数量。
实现跨通道的交互和信息整合;增强通道层面上特征融合的信息,在feature map尺度不变的情况下,实现通道升维、降维操作其实就是通道间信息的线性组合变化,也就是通道的信息交互整合的过程;
增加非线性;1*1卷积核可以在保持feature map尺度(不损失分辨率)不变的情况下,大幅增加非线性特性(利用后接的非线性激活函数)。
卷积神经网络中用1*1 卷积有什么作用或者好处呢?
- 卷积后再次应用非线性
梯度消失和梯度爆炸的原因是什么?怎么解决?
梯度消失和梯度爆炸问题都是因为网络太深,网络权值更新不稳定造成的,本质上是因为梯度反向传播中的连乘效应。
梯度消失和梯度爆炸的概念
根据损失函数计算的误差通过梯度反向传播的方式对深度网络权值进行更新时,得到的梯度值接近0或特别大,也就是梯度消失或爆炸。梯度消失或梯度爆炸在本质原理上其实是一样的。
梯度消失:令bias=0,则神经网络的输出结果等于各层权重参数的积再与输入数据集相乘,若参数值较小时,则权重参数呈指数级减小。
- 梯度爆炸:令bias=0,则神经网络的输出结果等于各层权重参数的积再与输入数据集相乘,若参数值较大时,则权重参数呈指数级增长。
分析产生梯度消失和梯度爆炸的原因
【梯度消失】:(1) 深层网络;(2) 不合适的激活函数(sigmoid)
【梯度爆炸】:(1) 深层网络;(2) 权重初始值太大
深层网络:
由于深度网络是多层非线性函数的堆砌,整个深度网络可以视为是一个复合的非线性多元函数(这些非线性多元函数其实就是每层的激活函数),那么对loss function求不同层的权值偏导,相当于应用梯度下降的链式法则,链式法则是一个连乘的形式,所以当层数越深的时候,梯度将以指数传播。
如果接近输出层的激活函数求导后梯度值大于1,那么层数增多的时候,最终求出的梯度很容易指数级增长,就会产生梯度爆炸;相反,如果小于1,那么经过链式法则的连乘形式,也会很容易衰减至0,就会产生梯度消失。
从深层网络角度来讲,不同的层学习的速度差异很大,表现为网络中靠近输出的层学习的情况很好,靠近输入的层学习的很慢,有时甚至训练了很久,前几层的权值和刚开始随机初始化的值差不多。因此,梯度消失、爆炸,其根本原因在于反向传播训练法则,属于先天不足。
激活函数:
类似 sigmoid 激活函数,在链式求导梯度回传过程中,返回的值很小,层数越多,求导结果越小,最终导致梯度消失的情况出现。
初始化权重过大
权重比较大的情况。根据链式相乘(反向传播)可得,则前面的网络层比后面的网络层梯度变化更快,很容易发生梯度爆炸的问题。所以在一般的神经网络中,权重的初始化一般都利用高斯分布(正态分布)随机产生权重值。
梯度消失和梯度爆炸的解决方案
pre-training + fine-tunning
Hinton在训练深度信念网络(Deep Belief Networks中,使用了这个方法,在各层预训练完成后,再利用BP算法对整个网络进行训练。此思想相当于是先寻找局部最优,然后整合起来寻找全局最优,此方法有一定的好处,但是目前应用的不是很多了。
梯度剪切:对梯度设定阈值
梯度剪切这个方案主要是针对梯度爆炸提出的,其思想是设置一个梯度剪切阈值,然后更新梯度的时候,如果梯度超过这个阈值,那么就将其强制限制在这个范围之内。这可以防止梯度爆炸。
权重正则化
解决梯度爆炸的手段是采用权重正则化(weithts regularization),正则化主要是通过对网络权重做正则来限制过拟合。如果发生梯度爆炸,那么权值就会变的非常大,反过来,通过正则化项来限制权重的大小,也可以在一定程度上防止梯度爆炸的发生。比较常见的是 L1 正则和 L2 正则,在各个深度框架中都有相应的API可以使用正则化。
选择 relu,leakrelu,elu等梯度大部分在常数上的激活函数
relu函数的导数在正数部分是恒等于1的,因此在深层网络中使用relu激活函数就不会导致梯度消失和爆炸的问题。
Batch Normalizaition (BN)
BN就是通过对每一层的输出规范为均值和方差一致的方法,消除了权重参数放大缩小带来的影响,进而解决梯度消失和爆炸的问题,或者可以理解为BN将输出从饱和区拉倒了非饱和区。
残差结构(shortcut)
比较于以前直来直去的网络结构,残差中有很多的跨层连接结构,这样的结构在反向传播中具有很大的好处,可以避免梯度消失。kaiming大佬的杰作!
欠拟合和过拟合
欠拟合是指模型不能在训练集上获得足够低的误差。
过拟合是指训练误差和测试误差之间的差距太大,神经网络对训练数据进行很好的建模但在看到来自同一问题域的新数据时失败的现象。
模型容量低,而训练数据复杂度高时,此时模型由于学习能力不足,无法学习到数据集中的“一般规律”,因而导致训练误差高,表现为欠拟合。
模型容量高,而训练数据简单时,此时模型由于学习能力太强,记住所有的训练数据,却没有理解数据背后的规律,对于训练集以外的数据泛化能力差,表现为过拟合。
解决欠拟合
- 在模型容量和训练数据复杂度不匹配时,发生了欠拟合现象,常见解决方法有:
- 增加新特征:可以考虑加入特征组合、高次特征等,来增大假设空间。
- 增大模型容量:容量低的模型可能很难拟合训练集。
- 减少正则化参数:正则化的目的是用来防止过拟合的,但是模型出现了欠拟合,则需要减少正则化参数。
解决过拟合
引起过拟合的主演原因如下:
- 训练数据集问题。如训练样本不均衡,训练集中正样本偏多,那么去预测负样本肯定不准;训练样本数据少,尤其是当比模型参数数量还少时,更容易发生过拟合;训练数据噪声干扰过大,模型会学习很多的噪声特征等。
- 模型过于复杂。模型参数数量太多,参数取值范围太大,模型已经能够“死记硬背”记下了所有训练数据的信息(记住了不适合于测试集的训练集特性);模型假设的合理性不存在,也就是假设成立的条件实际并不成立。
- 模型训练迭代次数太多。对数据反复地训练也可能会让模型拟合了训练样本中没有代表性的特征
解决过拟合问题,最重要的减少测试误差而不过度增加训练误差,从而提高模型的泛化能力。通常解决过拟合的方法有:
- 数据集增强
- 控制模型容量大小
- 正则化(Regularization)L1和L2
- 丢弃法(Dropout)
- 提前终止训练(Early Stopping)
Loss为Nan,为何?怎么解决?
排查顺序
- 是否有脏数据,训练数据(包括标签)是否有异常值(nan,inf等)
- 网络中是否有除法,分母可能出现0的情况,这种情况一般添加一个平滑项,+ eps=1e-8
- 开跟号,也是要保证根号下 >= 0的,这种情况也是添加平滑项
- 在某些涉及指数计算,可能最后算得值为INF(无穷)(比如不做其他处理的softmax中分子分母需要计算exp(x),值过大,最后可能为INF/INF,得到NaN,此时你要确认你使用的softmax中在计算exp(x)做了相关处理(比如减去最大值等等))
典型案例
梯度爆炸,
梯度变得非常大,使得学习过程难以继续。Loss随着每轮迭代越来越大,最终超过了浮点型表示范围,就变成NaN了,
改善措施:数据归一化(BN,L2 norm等);参数初始方法;学习率;batch-size;梯度截断;
不当的损失函数,
有时候损失层中loss的计算可能导致NaN的出现。比如,给InfogainLoss层(信息熵损失)输入没有归一化的值,使用带有bug的自定义损失层等等。
改善措施:重现错误,逐步排查。
不当的输入,
就是 training sample中出现了脏数据,脏数据导致网络输出的logits计算出了0,0计算损失得到NaN,
改善措施:找到脏数据剔除即可,设置batch-size=1,一个一个来判断。
深度学习中常用的优化器
Pytorch中优化器的目的:将损失函数计算出来的插值Loss减少。
优化过程:优化器计算网络参数的梯度,然后使用一定的算法策略来对参数进行计算,用新的参数来重进行训练,最终降低Loss。
SGD算法
SGD算法可以实现随机梯度下降,融合了动量梯度,权重衰减,没有自适应学习率机制,但仔细调参最终模型效果可能最好
基本思想:通过当前梯度和历史梯度共同调节梯度的方向和大小,所有参数共享一个学习率,对学习率敏感
torch.optim.SGD(params, lr= , momentum=0, damening=0, weight_decay=0, nesterov=False)
- params:可迭代参数以优化或定义参数组
- lr:初始学习率,可随着训练过程不断调整学习率
- momentum:动量,通常设置为0.9,0.8,又称动量梯度下降
- damening:动量阻尼,默认为0
- weight_decay:权值衰减系数,即L2正则化
随机梯度下降(SGD)、批量梯度下降(BSGD)、小批量随机梯度下降(MBGD)区别这三者的主要区别是训练数据的选择上
批量梯度下降:针对的是整个数据集,通过对所有的样本的计算求解梯度的方向**。每迭代一步,都要用到训练集所有的数据,如果样本数目很大,迭代速度会变得很慢。
- 优点:全局最优解,一次迭代对所有样本进行计算,此时利用向量化进行操作,实现了并行化
- 缺点:当样本数目很多时,训练过程会很慢。收敛非常慢。遍历完全数据才知道某些样本对参数的更新是多余的。
小批量梯度下降:在上述的批梯度的方式中每次迭代都要使用到所有的样本,对于数据量特别大的情况,如大规模的机器学习应用,每次迭代求解所有样本需要花费大量的计算成本。是否可以在每次的迭代过程中利用部分样本代替所有的样本呢?基于这样的思想,便出现了mini-batch的概念。这个就是折中的概念。对于深度学习模型而言,人们所说的“随机梯度下降, SGD”,其实就是基于小批量(mini-batch)的随机梯度下降。
- 优点:计算速度比BGD快,之便利部分样例就可以执行更新。随机选择有利于避免重复多余的样例和对参数更新较少贡献的样例。减少收敛需要的迭代次数,收敛效果接近梯度下降(BGD)的效果。
- 缺点:受噪音的影响,学习过程出现波动,在最小值的区域徘徊,不会收敛。学习过程会有更多的震荡,为了接近最小值,需要增加学习率衰减项。batch_size的不当选取可能会有影响。
随机梯度下降:机梯度下降是在每次迭代时使用一个样本来对参数进行更新(mini-batch size =1)。随机梯度下降在计算下降最快的方向时时随机选一个数据进行计算,而不是扫描全部训练数据集,这样就加快了迭代速度。随机梯度下降算法(stochastic gradient descent)可以看成是mini-batch gradient descent的一个特殊的情形,即在随机梯度下降法中每次仅根据一个样本对模型中的参数进行调整,等价于上述的b=1情况下的mini-batch gradient descent,即每个mini-batch中只有一个训练样本。
随机梯度下降是通过每个样本来迭代更新一次,如果样本量很大的情况(例如几十万),那么可能只用其中几万条或者几千条的样本,就已经将参数迭代到最优解了,对比上面的批量梯度下降,迭代一次需要用到十几万训练样本,一次迭代不可能最优,如果迭代10次的话就需要遍历训练样本10次。但是,SGD伴随的一个问题是噪音较BGD要多,使得SGD并不是每次迭代都向着整体最优化方向。
- 优点:训练速度快。加入了噪声,提高了泛化误差。
- 缺点:准确度下降,并不是全局最优,不易于并行实现。单个样本并不能代表全体样本的趋势。
(1)梯度下降:在梯度下降中,对于θ的更新,所有的样本都有贡献,也就是参与调整θ.其计算得到的是一个标准梯度。因而理论上来说一次更新的幅度是比较大的。如果样本不多的情况下,当然是这样收敛的速度会更快啦~
(2)随机梯度下降:可以看到多了随机两个字,随机也就是说我用样本中的一个例子来近似我所有的样本,来调整θ,因而随机梯度下降是会带来一定的问题,因为计算得到的并不是准确的一个梯度,容易陷入到局部最优解中
(3)批量梯度下降:其实批量的梯度下降就是一种折中的方法,他用了一些小样本来近似全部的,其本质就是我1个指不定不太准,那我用个30个50个样本那比随机的要准不少了吧,而且批量的话还是非常可以反映样本的一个分布情况的。
Adagrad算法
Adagrad(Adaptive Gradient)的核心思想是,深度模型带来的稀疏性,导致模型中一些参数可能频繁获得较大梯度,另一些参数偶尔获得较大梯度,若采用统一学习率导致后者的更新会非常缓慢。基于此,可以调节模型中不同参数的学习率,而不是用统一的学习率。如果一个参数的历史累计梯度更新量大,则降低该参数的学习率;如果一个参数的历史累计梯度更新量小,则增大该参数的学习率。
- Adagrad算法可以自适应的给所有的参数分配学习率,学习率的大小与梯度的大小成反比。
- 因为梯度有正有负所以对梯度的平方进行累计。
- 对每个参数分别调节学习率,也可以看成调节每个参数的梯度。
- 缺点是随着迭代次数增多,累计值越来越大,导致模型参数的实际更新越来微弱
RMSprop算法
RMSprop算法是Adagrad的改进形式,特点是使用指数衰减滑动平均来更新梯度平方,以避免Adagrad累计梯度平方导致学习率过小的缺点。区别于adagrad之处是它采用了EMA方式来统计每个参数的最近的累计梯度量,所以多次迭代后不会导致模型参数更新缓慢。
Adam算法
Adam(Adaptive Moment Estimation)优化算法,整合了RMSprop中的自适应梯度机制和动量梯度机制。Adam优化器实现中还加入了权重衰减机制。
可以自适应调节模型中不同参数的学习率,而不是用统一的学习率,所以对学习率相对不敏感。
torch.optim.Adam(network.parameters(), lr=learning_rate, betas=(0.9, 0.999), eps=1e-8, weight_decay=0.01, amsgrad=False)
AdamW算法
AdamW优化器修正了Adam中权重衰减的bug。
总结:
- SGD:没有自适应学习率机制,但仔细调参最终模型效果可能最好,需要慢慢调节学习率可以最佳效果。
- Adam:学习率相对不敏感,减少调参试验代价,没有条件调参建议采用也可以达到较好的水平。但weight decay实现不好,能用Adam的地方可以都用AdamW来代替。
- AdamW:相对于Adam,权重衰减(weight decay)实现解耦,效果更好,可代替Adam。
为什么输入网络前要对图像做归一化?
感受野的计算问题?
感受野(Receptive Field):卷积神经网络中每一层输出的特征图(feature map)中的每一个像素点在输入图片上映射的大小。也就是特征图上的一个像素点对应输入图上的区域。
感受野的计算:
最后一层(卷积层或者池化层)输出特征图感受野的大小等于卷积核的大小。
第i层卷积层的感受野大小和第i层的卷积核大小和步长有关系,同时也与第(i+1)层感受野大小相关。
计算感受野的大小时忽略图像边缘的影响,即不考虑padding大小。
关于感受野大小的计算方式是从最后一层往下计算的方法,即先计算最深层在前一层上的感受野,然后计算最深层在前二层上的感受野,然后依次递归到第一层,计算的流程和公式如下:
1、设要计算感受野的这层为第N层
2、第
N
层到第N-1
层的感受野就是对第N-1
层进行卷积时使用的卷积核大小,这里我们设为$RF_{N-1}$。3、接着计算第
N
层到第N-2
层的感受野大小,公式是:注意:这里的
stride
和kernel_size
是第N-2
层的
记住:两层3x3的卷积核的感受野为5,三层3X3的卷积核的感受野为7. 其中stride=1,padding=0
感受野计算的例子:
从最后一层的池化层开始计算感受野:
因此,pool3输出的特征图在输入图片上的感受野为30*30。
要从最后一层向前计算感受野,而不是从前往后计算感受野。
为什么用多个3X3的小卷积核代替大卷积和?(2个3X3代替5X5;3个3X3代替7X7)
(1)保证具有相同感知野的条件下,提升了网络的深度,在一定程度上提升了神经网络的效果;(2)减少计算参数量。
3x3是最小的能够捕获像素八邻域信息的尺寸。
- 两个3x3的堆叠卷基层的有限感受野是5x5;三个3x3的堆叠卷基层的感受野是7x7,故可以通过小尺寸卷积层的堆叠替代大尺寸卷积层,并且感受野大小不变。
- 多个3x3的卷基层比一个大尺寸filter卷基层有更多的非线性(更多层的非线性函数,使用了3个非线性激活函数)。
- 多个3x3的卷积层比一个大尺寸的filter有更少的参数。
- 唯一的不足是,在进行反向传播时,中间的卷积层可能会导致占用更多的内存;
MLP和卷积的区别
MLP:全连接神经网络,在视觉这边往往会存在如下两个问题
- 1、输入数据的空间信息被丢失。空间上相邻的像素点往往具有相似的RGB值,RGB的各个通道之间的数据通常密切相关,但是转化成1维向量时,这些信息被丢失。如 下图 所示,空间位置相邻的两个点A和B,转化成1维向量后并没有体现出他们之间的空间关联性。
- 2、模型参数过多,容易发生过拟合。由于每个像素点都要跟所有输出的神经元相连接。当图片尺寸变大时,输入神经元的个数会按图片尺寸的平方增大,导致模型参数过多,容易发生过拟合。
卷积(Convolution)来对输入的图像进行特征提取。卷积的计算范围是在像素点的空间邻域内进行的,因此可以利用输入图像的空间信息;此外,由于卷积具有局部连接、权重共享等特性,卷积核参数的数目也远小于全连接层。
- 局部连接:全连接层是一种稠密连接方式,而卷积层却只使用卷积核对局部进行处理,这种处理方式其实也刚好对应了图像的特点。在视觉识别中,关键性的图像特征、边缘、角点等只占据了整张图像的一小部分,相隔很远的像素之间存在联系和影响的可能性是很低的,而局部像素具有很强的相关性。
- 共享参数:如果借鉴全连接层的话,对于1000×1000大小的彩色图像,一层全连接层便对应于三百万数量级维的特征,即会导致庞大的参数量,不仅计算繁重,还会导致过拟合。而卷积层中,卷积核会与局部图像相互作用,是一种稀疏连接,大大减少了网络的参数量。另外从直观上理解,依靠卷积核的滑动去提取图像中不同位置的相同模式也刚好符合图像的特点,不同的卷积核提取不同的特征,组合起来后便可以提取到高级特征用于最后的识别检测了。
医学图像分割与自然图像分割的区别与难点
医学图像相比于自然图像(通过可见光成像)有以下区别:
- 医学图像的模态(格式)更加多样化,而且不同型号的成像设备得到的成像结果有一定差异。
- 医学图像的像素值范围与自然图像(0~255)有很大差别,如CT一般会上千。
- 噪声。由于成像设备、成像原理以及个体自身差异的影响,医学图像一般会含有很多噪声。由于噪声对于位置和空间约束是独立的,从而可以利用噪声的分布来实现降噪,但是在抑制噪声的同时也需要考虑图像细节的保留问题。
- 伪影。伪影一般是在图像配准或三维重建时产生(如CT),从原理上来,只能减少,无法消除。
- 成像原理带来的干扰,噪声,以及伪影。
深入理解医学图像的格式和特点;设计合适的图像预处理操作增强目标特征;将原始格式的数据处理为适合深度学习模型输入的格式。
医学图像相比于自然图像(通过可见光成像)有以下难点:
- 数据可用性:获取医学图像数据通常受到法规和伦理问题的限制。因此,医学图像的数据可用性通常有限。这使得在医学图像分割中使用深度学习方法变得更加具有挑战性,因为这些方法通常需要大量的标注数据。
- 标注困难:正确标注医学图像需要医学专业知识,而且通常需要专业人员的参与。这增加了标注的成本和时间,因为需要确保标注的准确性,以支持医学诊断。
- 类别不平衡:在医学图像中,不同的结构和组织可能出现的频率差异很大。例如,在肿瘤分割任务中,正例(肿瘤区域)通常比负例(非肿瘤区域)稀缺。这种类别不平衡可能导致模型对常见类别更为敏感,而忽略了罕见的类别。
- 模型泛化:由于医学图像数据有限,模型需要在不同的机器和数据集上进行有效的泛化,以在新的患者和医疗场景中进行准确的分割。这需要特殊的技术来处理数据集之间的差异。
- 数据量少,标注要求高。
- 在某些医学分割任务中,目标区域和背景区域的对比度极低,导致边界很难辨别。即使不是专业的医学人士都是很难通过肉眼辨别的。
改进小目标识别的几个有效策略
- 提升图像采集的分辨率:非常小的物体的边界框中可能只包含几个像素,这意味着增加图像的分辨率可以增加探测器可以从那个小盒子中形成的丰富特征,这是非常重要的。
- 提高模型的输入分辨率:有了更高分辨率的图像,你就可以放大模型的输入分辨率。警告:这将导致大型模型需要更长的时间来训练,并且当你开始部署时,也会更慢地进行推断。你可能需要实验来找出速度与性能之间的正确权衡。
- 对图像进行Tiling技术:检测小物体的另一个重要策略是将图像切割后形成batch,这个操作叫做tile,作为预处理步骤。tile可以有效地将检测器聚焦在小物体上,但允许你保持所需的小输入分辨率,以便能够运行快速推断。tile图像作为预处理步骤,如果你在训练中使用tile,重要的是要记住,你也需要在推理时tile你的图像。
- 通过增强产生更多数据:数据增强是一种提升小目标检测性能的最简单和有效的方法,通过不同的数据增强策略可以扩充训练数据集的规模,丰富数据集的多样性,从而增强检测模型的鲁棒性和泛化能力
- 多尺度学习:浅层特征图感受野小,更适合检测小目标,深层特征图较大,更适合检测大目标。因此,有人提出将不同阶段的特征映射整合在一起来提高目标检测性能,称之为特征金字塔网络FPN。。小目标与常规目标相比可利用的像素较少,难以提取到较好的特征,而且随着网络层数的增加,小目标的特征信息与位置信息也逐渐丢失,难以被网络检测。这些特性导致小目标同时需要深层语义信息与浅层表征信息,而多尺度学习将这两种相结合,是一种提升小目标检测性能的有效策略。
- 损失函数:可以在小目标的loss上施加更高的权重,使得网络更关注小目标的优化。