深度学习是算法工程师面试必定绕不开的一个话题,有关于他的面试题目和知识点层出不穷,所以这里依靠一些经验结合自己的面试经历,总结出下面的深度学习面试点,其中共有8个章节,目前更新章节1。
希望能帮助到各位秋招和暑期实习的同学们,感兴趣的可以点波关注+点赞收藏,你们的支持是俺坚持的动力呢!
算法工程师关于机器学习,其面经系列的其他部分如下所示:
机器学习面经-part1
机器学习-面经(part2)-交叉验证、超参数优化、评价指标等内容
机器学习-面经(part3)-正则化、特征工程面试问题与解答合集机器学习-面经(part4)-决策树共5000字的面试问题与解答
机器学习-面经(part5)-KNN以及SVM等共二十多个问题及解答
机器学习-面经(part6)-集成学习(万字解答)
机器学习-面经(part7、无监督学习)
1.在前向传播和反向传播过程中,ReLU相比于Sigmoid等激活函数计算量小;
2.避免梯度消失问题。对于深层网络,Sigmoid函数反向传播时,很容易就会出现梯度消失问题(在Sigmoid接近饱和区时,变+换太缓慢,导数趋于0,这种情况会造成信息丢失),从而无法完成深层网络的训练。
3.可以缓解过拟合问题的发生。Relu会使一部分神经元的输出为0,这样就造成了网络的稀疏性,并且减少了参数的相互依存关系,缓解了过拟合问题的发生。
4.相比Sigmoid型函数,ReLU函数有助于随机梯度下降方法收敛。
激活函数在神经网络中起到了至关重要的作用,它能够将输入信号转化为输出信号,引入非线性,增加网络的表达能力。激活函数的作用主要体现在以下几个方面:
引入非线性:线性函数的叠加仍然是线性的,而神经网络需要具备处理非线性问题的能力。激活函数通过引入非线性,使得神经网络可以处理更加复杂的问题,提高网络的表达能力。
压缩输出范围:激活函数可以将神经元的输出限制在一定的范围内,如[0, 1]或[-1, 1]。这种限制可以使得神经网络的输出更加稳定,有助于提高网络的收敛速度和性能。
增加网络的非线性响应:激活函数的非线性特性可以使得神经网络对输入的微小变化更加敏感,从而提高网络的灵敏度和鲁棒性。
梯度消失:靠近输出层的hidden layer 梯度大,参数更新快,所以很快就会收敛;
而靠近输入层的hidden layer 梯度小,参数更新慢,几乎就和初始状态一样,随机分布。
另一种解释:当反向传播进行很多层的时候,由于每一层都对前一层梯度乘以了一个小数,因此越往前传递,梯度就会越小,训练越慢。
梯度爆炸:前面layer的梯度通过训练变大,而后面layer的梯度指数级增大。
①在深度多层感知机(MLP)网络中,梯度爆炸会引起网络不稳定,最好的结果是无法从训练数据中学习,而最坏的结果是出现无法再更新的 NaN 权重值。
②在RNN中,梯度爆炸会导致网络不稳定,无法利用训练数据学习,最好的结果是网络无法学习长的输入序列数据。
残差网络解决梯度消失和爆炸:
模型不稳定,导致更新过程中的损失出现显著变化;
训练过程中模型梯度快速变大;
训练过程中模型权重变成 NaN 值;
训练过程中,每个节点和层的误差梯度值持续超过 1.0。
L2正则化(Ridge); L1正则化(Lasso); 权重衰减;丢弃法;批量归一化;数据增强;早停法;
梯度饱和是进入到某一个区间之后梯度变化较小
实现过程: 计算训练阶段mini_batch数量激活函数前结果的均值和方差,然后对其进行归一化,最后对其进行缩放和平移。
作用: 1.可以使用更高的学习率进行优化;
2.移除或使用较低的 dropout;
3.降低L2权重衰减系数;
4.调整了数据的分布,不考虑激活函数,它让每一层的输出归一化到了均值为0方差为1的分布,这保证了梯度的有效性,可以解决反向传播过程中的梯度问题。
权值共享这个词是由LeNet5模型提出来的。以CNN为例,在对一张图偏进行卷积的过程中,使用的是同一个卷积核的参数。
比如一个3×3×1的卷积核,这个卷积核内9个的参数被整张图共享,而不会因为图像内位置的不同而改变卷积核内的权系数。
通俗说:就是用一个卷积核不改变其内权系数的情况下卷积处理整张图片。
使用预训练模型的好处:在于利用训练好的SOTA模型权重去做特征提取,可以节省我们训练模型和调参的时间。
理由:
1.CNN中更靠近底部的层(定义模型时先添加到模型中的层)编码的是更加通用的可复用特征,而更靠近顶部的层(最后添加到模型中的层)编码的是更专业化的特征。微调这些更专业化的特征更加有用,它更代表了新数据集上的有用特征。
2.训练的参数越多,过拟合的风险越大。很多SOTA模型拥有超过千万的参数,在一个不大的数据集上训练这么多参数是有过拟合风险的,除非你的数据集像Imagenet那样大。
背景:如果模型的参数太多,数据量又太小,则容易产生过拟合。为了解决过拟合,就同时训练多个网络。然后多个网络取均值。费时!
介绍:Dropout可以防止过拟合,在前向传播的时候,让某个神经元的激活值以一定的概率 P停止工作,这样可以使模型的泛化性更强。
Dropout效果跟bagging效果类似(bagging是减少方差variance,而boosting是减少偏差bias)。
加入dropout会使神经网络训练时间长,模型预测时不需要dropout,记得关掉。
具体流程:
i.随机删除(临时)网络中一定的隐藏神经元,输入输出保持不变,
ii.让输入通过修改后的网络。然后把得到的损失同时修改后的网络进行反向传播。在未删除的神经元上面进行参数更新
iii.重复该过程(恢复之前删除掉的神经元,以一定概率删除其他神经元。前向传播、反向传播更新参数)
- 这样的话每次都次迭代的神经网络都是不同的,相当于多个神经网络模型的集合,但是要训练的参数数目是不变的,这就解决了费时的问题。
- Dropout强迫一个神经单元,和随机挑选出来的其他神经单元共同工作,达到好的效果。消除减弱了神经元节点间的联合适应性,增强了泛化能力
- 在迭代过程中随机关闭一些神经元,那么模型将不会对某一个或一些神经元特别‘敏感’,因为无论哪个神经元随机都有被关闭的风险
input 的 dropout 概率推荐是 0.8, hidden layer 推荐是0.5
为什么dropout可以解决过拟合?
1.取平均的作用:
Dropout产生了许多子结构之后的操作,父神经网络有N个节点,加入Dropout之后可以看做在权值不变的情况下(参数共享)将模型数量扩增到指数级别
2.减少神经元之间复杂的共适应关系,迫使网络去学习更加鲁棒;
Dropout 在训练和测试的区别?
训练时随机删除一些神经元,在测试模型时将所有的神经元加入。
所有的优化算法都可以用下面一个框架表示:
相当全乎的连接:一个框架看懂优化算法之异同 SGD/AdaGrad/Adam - 知乎
一阶优化方法有:
SGD -> SGDM ->NAG -> AdaGrad -> AdaDelta / RMSProp(加速梯度下降) -> Adam -> Nadam
二阶优化
定义:对目标函数进行二阶泰勒展开,也就是二阶梯度优化方法
牛顿法 + BFGS法
利用二阶泰勒展开,即牛顿法需要计算Hessian矩阵的逆,计算量大,在深度学习中并不常用。因此一般使用的是一阶梯度优化。
动量其实累加了历史梯度更新方向,所以在每次更新时,要是当前时刻的梯度与历史时刻梯度方向相似,这种趋势在当前时刻则会加强;要是不同,则当前时刻的梯度方向减弱。动量方法限制了梯度更新方向的随机性,使其沿正确方向进行。
Adam等自适应学习率算法对于稀疏数据具有优势,且收敛速度很快;
但精调参数的SGD(+Momentum)往往能够取得更好的最终结果
Adam+SGD 组合策略:先用Adam快速下降,再用SGD调优。
如果模型是非常稀疏的,那么优先考虑自适应学习率的算法;
在模型设计实验过程中,要快速验证新模型的效果,用Adam进行快速实验优化;
在模型上线或者结果发布前,可以用精调的SGD进行模型的极致优化。
online learning强调的是学习是实时的,流式的,每次训练不用使用全部样本,而是以之前训练好的模型为基础,每来一个样本就更新一次模型,这种方法叫做OGD(online gradient descent),目的是快速地进行模型的更新,提升模型时效性。而SGD的思想正是在线学习的思想。
1.基于经验的手动调整
通过尝试不同的固定学习率,如3、1、0.5、0.1、0.05、0.01、0.005,0.0001等,观察迭代次数和loss的变化关系,找到loss下降最快关系对应的学习率。
太小,收敛过程将变得十分缓慢;
太大,梯度可能会在最小值附近来回震荡(loss爆炸),甚至可能无法收敛。
2. 基于策略的调整
①fixed 、exponential、polynomial
②自适应动态调整。adadelta、adagrad、ftrl、momentum、rmsprop、sgd
Logit:对它取对数。
牛顿法原理:使用函数f(x)的泰勒级数的前面几项来寻找方程f(x)= 0的根。
BN:
训练时:是对每一个batch的训练数据进行归一化,也即是用每一批数据的均值和方差。
测试时:都是对单个样本进行测试。这个时候的均值和方差是全部训练数据的均值和方差,这两个数值是通过移动平均法求得。
当一个模型训练完成之后,它的所有参数都确定了,包括均值和方差,gamma和bata。
Dropout:只有在训练的时候才采用,是为了减少神经元对部分上层神经元的依赖,类似将多个不同网络结构的模型集成起来,减少过拟合的风险。
如果神经网络的参数被初始化为全零(或接近全零)的情况,会引发一些问题,这些问题通常被称为"权重均初始化"(Weight Initialization)问题。
对称性问题:如果所有的权重都初始化为相同的值,那么在反向传播算法中,所有神经元的梯度将相同,导致它们在训练过程中都学习到相同的特征表示。这会降低网络的表达能力。
梯度消失问题:如果权重初始化为零或接近零,那么在反向传播中,梯度信号会传播得非常慢,导致底层神经元几乎不更新,这被称为梯度消失问题。这会影响深度神经网络的训练,使得它们难以学习复杂的特征。
缺乏随机性:引入一些随机性有助于打破对称性和解决梯度消失问题。如果所有权重都相同,每个神经元都会计算相同的激活值,这对于模型来说是无意义的。
为了解决这些问题,通常会采用合适的权重初始化策略,如Xavier/Glorot初始化或He初始化,这些方法可以有效地设置权重,以促进网络的训练和性能提升。这些初始化策略考虑到了神经网络的结构和激活函数的特性,以确保梯度能够在训练中传播,并且不容易陷入梯度消失问题。初始化策略的选择通常依赖于具体的网络结构和任务。
1.Large Margin Softmax Loss (L-Softmax)
加了一个margin,要保证大于某一个阈值。这样可以尽量实现让类间间距更大化,类内距离更小。
2.Center Loss
通过将特征和特征中心的距离和softmax loss一同作为损失函数,使得类内距离更小,有点L1,L2正则化。
1.准备数据
1.1 保证有大量、高质量并且带有干净标签的数据;
1.2 样本要随机化,防止大数据淹没小数据;
1.3 样本要做归一化.
2.预处理:0均值和1方差化
3.minibatch:建议值128,不要用过大的数值,否则很容易过拟合
4.梯度归一化:其实就是计算出来梯度之后,要除以minibatch的数量。
5.学习率
5.1 用一个一般的lr开始,然后逐渐的减小它;
5.2 建议值是0.01,适用于很多NN的问题,一般倾向于小一点;
5.3 对于调度学习率的建议:如果在验证集上性能不再增加就让学习率除以2或者5,然后继续,学习率会一直变得很小,到最后就可以停止训练了。
5.4 很多人用的一个设计学习率的原则就是监测一个比率(范数和权值范数之间的比率),如果这个比率在10-3附近,如果小于这个值,学习会很慢,如果大于这个值,那么学习很不稳定,由此会带来失败。
6.使用验证集,可以知道什么时候开始降低学习率,和什么时候停止训练。
7.权重初始化的选择:
7.1 用高斯分布乘上一个很小的数
7.2 在深度网络中,随机初始化权重,使用SGD的话一般处理的都不好,这是因为初始化的权重太小了。这种情况下对于浅层网络有效,但是当足够深的时候就不行了,因为weight更新的时候,是靠很多weight相乘的,越乘越小,有点类似梯度消失。
8.如果训练RNN或者LSTM,务必保证gradient的norm被约束在15或者5(前提还是要先归一化gradient),这一点在RNN和LSTM中很重要。
9.Adam收敛速度的确要快一些,可结果往往没有sgd + momentum的解好(如果模型比较复杂的话,sgd是比较难训练的,这时候用adam较好)
10.如果使用LSTM来解决长时依赖的问题,记得初始化bias的时候要大一点
11.尽可能想办法多的扩增训练数据,如果使用的是图像数据,不妨对图像做一点扭转之类的操作,来扩充数据训练集合。
12.使用dropout。
1.early stop,发现val_loss没更新,就尽早停止。
2.评价最终结果的时候,多做几次,然后平均一下他们的结果。
损失函数的选择是否是合适的
学习率的选取是否合适
batch size选择是否合适
训练样本是否正常,是否需要增强
是否有设置batch normlaztion(数据归一化)
激活函数的类型需要选取恰当
选取合适的优化算法(例如梯度下降,Adam等)
是否存在过拟合
没必要。对于加了L1正则的神经网络,大部分深度学习框架自带的优化器训练获得不了稀疏解;如果稀疏解的模式是无规律的,这种稀疏意义不大。
零均值:每一维原始数据减去每一维数据的平均值, X -= np.mean(X,axis=0)
归一化:方法一是先进行零均值再将每一维数据除以标准差;方法二是将不同维度的数据归一到相同数值区间
CV中常见的预处理:对比度归一化、数据增强
a:将所有的参数初始化为0
b:对w随机初始化
c: Xavier初始化:尽可能的让输入和输出服从相同的分布,这样就能够避免后面层的激活函数的输出值趋向于0
d: 何氏初试法:针对relu的初始化方式
四种初始化方式的介绍:深度学习中神经网络的几种权重初始化方法_神经网络权重初始化方法-CSDN博客
如果权重初始化太小,会导致神经元的输入过小,随着层数的不断增加,会出现信号消失的问题;也会导致sigmoid激活函数丢失非线性的能力,因为在0附近sigmoid函数近似是线性的。如果参数初始化太大,会导致输入状态太大。
对sigmoid激活函数来说,激活函数的值会变得饱和,从而出现梯度消失的问题。
VGG16(在DL应用中经常使用16个隐藏层的卷积神经网络)大约具有1.4亿个参数,又称权重和偏见。如果用传统的方法,训练这种系统需要几年的时间。
神经网络的计算密集部分由多个矩阵乘法组成,可以简单地通过同时执行所有操作,而不是一个接一个地执行,要使用GPU(图形处理单元)而不是CPU来训练神经网络。
FNN 是指在一个vector内部的不同维度之间进行一次信息交互。
CNN是以逐次扫描的方式在一个vector的局部进行多次信息交互。
RNN就是在hidden state上增加了loop,看似复杂,其实就是从时间维度上进行了展开。是在不同时刻的多个vectors之间进行信息交互。
1.模型蒸馏技术;
2.利用AutoML进行网络结构的优化。
欧氏距离,交叉熵,对比损失,合页损失
均方误差:计算实际值和预测值之间的平方差的平均值来计算
绝对值误差:MAE
梯度为0,海森矩阵不定的点,不是极值点。
通常一阶导数为0的点称为稳定点,可以分为三类: 局部最小点,局部最大点,鞍点
一般区分鞍点和局部最优的方法是使用神经网络 loss surface 的 Hessian 矩阵,通过计算 Hessian 矩阵的特征值,进行判断:
- 当 Hessian 矩阵的特征值有正有负的时候,神经网络的一阶导数为 0 的点是鞍点;
- 当 Hessian 矩阵的特征值是非负的时候,神经网络的一阶导数为 0 的点是局部极小值点;
- 当 Hessian 矩阵最小特征值小于零,则为严格鞍点(包含了局部最大)
若某个一阶导数为0的点在至少一个方向上的二阶导数小于0,那它就是鞍点。最优点和鞍点的区别在于其在各个维度是否都是最低点。只要某个一阶导数为0的点在某个维度上是最高点而不是最低点,那它就是鞍点。而区分最高点和最低点当然就是用二阶导数,斜率从负变正的过程当然就是“下凸”,即斜率的导数大于0,即二阶导数大于0。反之则为“上凹”,二阶导数小于0。
实际上,我们并不需要害怕陷入局部最小值,原因有这几个:
- 第一个,很直观的解释来自于上面特征值的分布信息:当loss很小的时候,我们才会遇到局部最小值问题,也就是说这时候的loss已经足够小,我们对这时候的loss已经足够满意了,不太需要花更大力气去找全局最优值。
- 第二个,在一定假设条件下,很多研究表明深度学习中局部最小值很接近于全局最小值。
- 保证像素点中心位置,避免位置信息偏移
- 填充边缘时能保证两边都能填充,原矩阵依然对称