深度学习面试常见问题集锦

这篇文章用来记录总结深度学习领域常见面试题。题目来源于各大门户网站和招聘网站。一来用于了解当前面试常考热点问题,二来在工作闭门造车的同时,弥补下自己深度学习理论方面的不足。

深度学习模型中参数量的计算?

全连接层

假设输入层大小i,隐藏层h,输出层o:

则参数量为各层之间的参数+每层的偏差=(ih+ho)+(h+o)

例如输入大小3,隐藏层大小5,输出大小2:

"1"

则参数个数为:(3×5 + 5×2)+(5 + 2) = 32

对于rnn网络

首先我们定义三个参数:g:门的数量(RNN有1个门,GRU有3个,LSTM有4个)h:隐藏单元大小 ,i:输出层大小每个门中的权重实际上是一个输入大小(h + i)(解释:上一个时刻的隐状态和当前输入的拼接)和输出大小为h(解释:当前时刻的隐状态)的FFNN。所以每个门都有h(h + i)+ h个参数。即在RNN中参数数量为:g × [ h(h + i)+ h ]
注意:输出我们只关心h,不关心其上层的全连接或者softmax,因为这已经不是当前rnn的参数了。
举例:具有2个隐藏单元和输入尺寸3的LSTM:

"2"

则参数量为:g ×[ h(h + i)+ h ]= 4 ×[2(2 + 3)+ 2] = 48

具有5个隐藏单元和输入大小为8的堆叠双向GRU +具有50个隐藏单元的LSTM的参数数量为:

"3"

第一层参数:2 × g ×[ h(h + i)+ h ] = 2 ×3×[5(5 + 8)+ 5] = 420
第二层参数: g ×[ h(h + i)+ h ]= 4×[50(50 + 10)+ 50] = 12200
则总参数量为: 420 + 12200 = 12620

对于CNN网络

首先我们定义三个参数:i:输入尺寸,f:卷积核的大小,o:输出大小

则每个滤波器对应的输出映射参数为:num_params =权重+偏差= [ i×(f×f)×o ] + o

例如带有1 × 1滤波器的灰度图像,输出3个通道
"4"

参数数量为: [ i×(f×f)×o ] + o= [1 ×(2 × 2)× 3] + 3= 15

例如具有2×2滤波器的RGB图像,1通道的输出。则每个输入像素通道都有1个滤波器。产生的卷积按元素叠加,并且向每个元素添加偏差项。
"5"

最终得到参数数量为: [ i×(f×f)×o ] + o= [3 ×(2×2)×1] + 1 = 13

卷积神经网络在max pooling处怎么反向传播误差

无论max pooling还是mean pooling,都没有需要学习的参数。因此,在卷积神经网络的训练中,Pooling层需要做的仅仅是将误差项传递到上一层,而没有梯度的计算。
(1)max pooling层:对于max pooling,下一层的误差项的值会原封不动的传递到上一层对应区块中的最大值所对应的神经元,而其他神经元的误差项的值都是0;
(2)mean pooling层:对于mean pooling,下一层的误差项的值会平均分配到上一层对应区块中的所有神经元。

怎么防止模型过拟合?

包括但不限于以下:

  • 提前终止(当验证集上的效果变差的时候)
  • 正则化(Regularization)
    L1正则化
    L2正则化
  • 数据集扩增(Data augmentation)
  • Dropout

GN,BN,LN和IN的区别?

"6"

  • BN是在batch上,对N,H,W做归一化,对小batchsize效果不好,应优先考虑
  • LN在通道方向上,对C,H,W做归一化,主要用于RNN
  • IN在图像像素上,对H, W做归一化,主要用于风格迁移, GAN
  • GN将通道分组,然后归一化,适合mini-batch很小的情况
  • SN将BN,LN,IN结合,赋予权重,让网络自适应归一化层

基于机器学习领域的一个重要的假设:iidiidiid假设,即假设训练数据和测试数据是满足相同的分布的,这是通过训练数据集获得的模型能够在测试集上获得好的效果的一个基本保障。

Batch Normalization

那么BN,简单的说,就是在深度神经网络训练过程中使得每一层神经网络的输入保持相同的分布。
"1"

但是也有不少问题:

  • 如果batch size太小,则BN效果明显下降
  • 对于有些像素级图片生成任务,效果不佳
  • 不适合RNN等动态网络,不方便且效果不佳
  • 训练时和推理时统计量不一致

Layer Normalization

为了能够在只有当前一个训练实例下,找到一个合理的统计范围,一个直接的想法是:把同一个卷积层作为集合,求均值和方差;对于RNN,就是把同层隐层神经元的响应值(不同时刻)作为集合,再求均值和方差。

Instance Normalization

LN是对所有的通道,那对一个通道做归一化是怎样呢!IN就是这么做的,单个通道的feature map作为集合,并在此集合上求均值和方差,这种像素级上的操作,使得IN对于一些图片生成类的任务效果明显优于BN,比如图片风格转换。

Group Normalization

LN是对于所有的通道,IN是对于单个通道,如果把所有通道分组,再各个组上做归一化又会怎样呢?这就是GN啦。通道分组也是CNN常用的优化技巧。GN在mini-batch比较小的场景或者物体检测、视频分类等场景下效果优于BN。

Switchable Normalization

归一化,虽能提高模型的泛化能力,但BN,LN, IN, GN都是人工设计的,是否可以放开手脚,让网络自适应呢!这是个更加generic的做法。

python浅拷贝和深拷贝的区别

在python中,对象赋值实际上是对象的引用。当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用。
一般有3种方法:

1
alist=[1,2,3,["a","b"]]

(1)直接赋值,默认浅拷贝传递对象的引用而已,原始列表改变,被赋值的b也会做相同的改变

1
2
3
4
5
6
7
>>> b=alist
>>> print b
[1, 2, 3, ['a', 'b']]
>>> alist.append(5)
>>> print alist;print b
[1, 2, 3, ['a', 'b'], 5]
[1, 2, 3, ['a', 'b'], 5]

(2)copy浅拷贝,没有拷贝子对象,所以原始数据改变,子对象会改变

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> import copy

>>> c=copy.copy(alist)
>>> print alist;print c
[1, 2, 3, ['a', 'b']]
[1, 2, 3, ['a', 'b']]
>>> alist.append(5)
>>> print alist;print c
[1, 2, 3, ['a', 'b'], 5]
[1, 2, 3, ['a', 'b']]

>>> alist[3]
['a', 'b']
>>> alist[3].append('cccc')
>>> print alist;print c
[1, 2, 3, ['a', 'b', 'cccc'], 5]
[1, 2, 3, ['a', 'b', 'cccc']] 里面的子对象被改变了

(3)深拷贝,包含对象里面的自对象的拷贝,所以原始对象的改变不会造成深拷贝里任何子元素的改变

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>> import copy

>>> d=copy.deepcopy(alist)
>>> print alist;print d
[1, 2, 3, ['a', 'b']]
[1, 2, 3, ['a', 'b']]始终没有改变
>>> alist.append(5)
>>> print alist;print d
[1, 2, 3, ['a', 'b'], 5]
[1, 2, 3, ['a', 'b']]始终没有改变
>>> alist[3]
['a', 'b']
>>> alist[3].append("ccccc")
>>> print alist;print d
[1, 2, 3, ['a', 'b', 'ccccc'], 5]
[1, 2, 3, ['a', 'b']] 始终没有改变

为什么2个3 * 3跟1个5 * 5感受野相同?

我们假设图片是28 * 28的,我们使用5 * 5的卷积核对其卷积,步长为1,得到的结果是:(28-5)/1+1=24,然后我们使用2个卷积核为3 * 3的,这里的两个是指2层:第一层3 * 3:得到的结果是(28-3)/1+1=26,第二层3 * 3:,得到的结果是(26-3)/1+1=24,所以我们的最终结果和5 * 5的卷积核是一样。

请解释为什么两层3x3的卷积核感受野为5x5,三层3x3的卷积核感受野为7x7呢?

角度一:在stride=1,padding=0的情况下,两层3x3的卷积核感受野为5x5,如下
"1"

三层3x3的卷积核感受野为7x7,如下
"2"

角度二:我们假设图片是28 * 28的,我们使用5 * 5的卷积核对其卷积,步长为1,得到的结果是:(28-5)/1+1=24。然后我们使用2个卷积核为3 * 3的,这里的两个是指2层:第一层3 * 3:得到的结果是(28-3)/1+1=26,第二层3 * 3:得到的结果是(26-3)/1+1=24,所以我们的最终结果和5 * 5的卷积核是一样的;其他同理。

图片直观感受法:10x10的图片使用3x3的卷积核卷积,默认stride=1,padding=0

"3"
"4"
2层3x3卷积核——output2中1x1的像素已经可以感受原图中的5x5区域了
"5"
3层3x3卷积核——output3中1x1的像素已经可以感受原图中的7x7区域了

为什么使用3x3的卷积核?

(1)3x3是最小的能够捕获像素八邻域信息的尺寸。
(2)两个3x3的堆叠卷基层的有限感受野是5x5;三个3x3的堆叠卷基层的感受野是7x7,故可以通过小尺寸卷积层的堆叠替代大尺寸卷积层,并且感受野大小不变。
(3)多个3x3的卷基层比一个大尺寸filter卷基层有更多的非线性(更多层的非线性函数,使用了3个非线性激活函数)。
(4)多个3x3的卷积层比一个大尺寸的filter有更少的参数,如三个3x3的卷积层参数个数3x((3x3xC)xC)=27C2;一个(7x7xC)xC的卷积层参数为49C2。唯一的不足是,在进行反向传播时,中间的卷积层可能会导致占用更多的内存;

batch normalization的均值和方差怎么更新的?

Batchnorm是归一化的一种手段,极限来说,这种方式会减小图像之间的绝对差异,突出相对差异,加快训练速度,如果我们每一个batch输入的数据都具有不同的分布,显然会给网络的训练带来困难。另一方面,数据经过一层层网络计算后,其数据分布也在发生着变化,会给下一层的网络学习带来困难。batchnorm就是为了解决这个分布变化问题。BatchNorm就是对神经网络的每一层进行归一化,假设将每一层输出后的数据都归一化到0均值,1方差,满足正太分布,但是,此时有一个问题,每一层的数据分布都是标准正太分布,导致其完全学习不到输入数据的特征,因为,费劲心思学习到的特征分布被归一化了,因此,直接对每一层做归一化显然是不合理的。但是如果稍作修改,加入可训练的参数做归一化,那就是BatchNorm实现的了
"2"
之前也说过如果直接做归一化不做其他处理,神经网络是学不到任何东西的,但是加入这两个参数后,事情就不一样了,先考虑特殊情况下,如果γ和β分别等于此batch的标准差和均值,那么 不就还原到归一化前的x了吗,也即是缩放平移到了归一化前的分布,相当于batchnorm没有起作用,β和γ分别称之为 平移参数和缩放参数 。这样就保证了每一次数据经过归一化后还保留的有学习来的特征,同时又能完成归一化这个操作,加速训练。batchnorm是在输入值和激活函数之间进行的,每次训练给一个批量,然后计算批量的均值方差,但是在测试的时候可不是这样,测试的时候每次只输入一张图片,这怎么计算批量的均值和方差,于是,在训练的时候实现计算好mean var测试的时候直接拿来用就可以了,不用计算均值和方差

ResNet旁路跟卷积后的结果相加具体是怎么做的?

1*1的卷积核有什么用

1×1卷积核用于升维、降维:如果卷积的输入、输出都仅有一个平面,那么1×1卷积核并没有啥意义。它完全不考虑像素与其周围像素之间的关系!但通常卷积的输入、输出都是立方体(多通道的),此时1×1卷积核实际上是对每个像素点在不同通道(channels)上线性组合(信息整合),且保留了图片的原有平面结构,仅仅是改变channels的数量,进而达到升维和降维的功能!

"7"

上左图显示了1×1卷积核用于降维。输入为4×4的平面,共3个通道。用两个1×1的卷积核(卷积层)作用之后,变为4×4的平面,共2通道。同理,上右图展示了升维的操作。

若卷积核数量如果与输入保持相同,则单纯地向网络增加非线性。

1、降维(通道数)  
通过控制卷积核的数量达到通道数大小的放缩。而池化层只能改变高度和宽度,无法改变通道数。
2、增加非线性  
如上所述,1×1卷积核的卷积过程相当于全连接层的计算过程,并且还加入了非线性激活函数,从而可以增加网络的非线性,使得网络可以表达更加复杂的特征。
3、减少卷积核参数,运算的复杂度  
在Inception Network中,由于需要进行较多的卷积运算,计算量很大,可以通过引入1×1确保效果的同时减少计算量。具体可以通过下面例子量化比较。

未引入1×1卷积的卷积操作:
"8"
卷积核参数:5x5x32x192
引入1×1卷积的卷积操作:
"9"
卷积核参数为1×1×192×16+5×5×16×32

深度学习中压缩模型的方法?

(1)设计轻量级的模型(SqueezeNet,MobileNet,ShuffleNet等):不需要压缩;
(2)模型结构/内存优化:剪枝、权值量化等;
(3)模型蒸馏

softmax与交叉熵(Cross Entropy)的区别与联系

参考:https://blog.csdn.net/weixin_42423701/article/details/90553196

随机森林+过拟合?

相对于单个的Decision Tree,Random Forest不太容易over-fitting。Over-fitting的主要原因是因为模型学习了太多样本中的随机误差。因为Random Forest随机选择了样本和特征,并且将很多这样的随机树进行了平均,这些随机误差也随之被平均,乃至相互抵消了。但是这不代表它不会很多人说Random Forest不会over-fitting。相信很多人也亲身经历过,我自己也见识过过RandomForest over-fitting了。防止RandomFroest过拟合,一个方法是控制每个树的深度,深的树有可能会过拟合;另外一个是对模型进行交叉验证。

可迭代对象、迭代器、生成器、装饰器:

  • 容器是一系列元素的集合,str、list、set、dict、file、sockets对象都可以看作是容器,容器都可以被迭代(用在for,while等语句中),因此他们被称为可迭代对象。
  • 可迭代对象实现了__iter__方法,该方法返回一个迭代器对象。
  • 迭代器持有一个内部状态的字段,用于记录下次迭代返回值,它实现了__next__和__iter__方法,迭代器不会一次性把所有元素加载到内存,而是需要的时候才生成返回结果。
  • 生成器是一种特殊的迭代器,它的返回值不是通过return而是用yield。
  • 装饰器可以让已有的函数不做任何改动的情况下增加功能。

数据不均衡如何处理?

  • 对较多的那个类别进行**欠采样(under-sampling)**,舍弃一部分数据,使其与较少类别的数据相当;(注释:已经改变了数据的分布,浪费了部分数据)
  • 对较少的类别进行**过采样(over-sampling)**,重复使用一部分数据,使其与较多类别的数据相当;(注释:已经改变了分布,数据重复生成,容易过拟合)
  • 阈值调整(threshold moving),将原本默认为0.5的阈值调整到 较少类别/(较少类别+较多类别)即可或者使用现有的集成学习分类器,如随机森林或者xgboost,并调整分类阈值。(推荐这种)

有1千万条短信,有重复,以文本文件的形式保存,一行一条,有重复。请用5分钟时间,找出重复出现最多的前10?

  • 方法1:可以用哈希表的方法对1千万条短信分成若干组进行边扫描边建散列表。第一次扫描,取首字节,尾字节,中间随便两字节作为Hash Code,插入到hash table中。并记录其地址和信息长度和重复次数,1千万条信息,记录这几个信息还放得下。同Hash Code且等长就疑似相同,比较一下。相同记录只加1次进hash table,但将重复次数加1。一次扫描以后,已经记录各自的重复次数,进行第二次hash table的处理。用线性时间选择可在O(n)的级别上完成前10条的寻找。分组后每份中的top10必须保证各不相同,可hash来保证,也可直接按hash值的大小来分类。

  • 方法2:可以采用从小到大排序的方法,根据经验,除非是群发的过节短信,否则字数越少的短信出现重复的几率越高。建议从字数少的短信开始找起,比如一开始搜一个字的短信,找出重复出现的top10并分别记录出现次数,然后搜两个字的,依次类推。对于对相同字数的比较常的短信的搜索,除了hash之类的算法外,可以选择只抽取头、中和尾等几个位置的字符进行粗判,因为此种判断方式是为了加快查找速度但未能得到真正期望的top10,因此需要做标记;如此搜索一遍后,可以从各次top10结果中找到备选的top10,如果这top10中有刚才做过标记的,则对其对应字数的所有短信进行精确搜索以找到真正的top10并再次比较。

  • 方法3:可以采用内存映射的办法,首先1千万条短信按现在的短信长度将不会超过1G空间,使用内存映射文件比较合适。可以一次映射(当然如果更大的数据量的话,可以采用分段映射),由于不需要频繁使用文件I/O和频繁分配小内存,这将大大提高数据的加载速度。其次,对每条短信的第i(i从0到70)个字母按ASCII嘛进行分组,其实也就是创建树。i是树的深度,也是短信第i个字母。

为什么正则化能阻止overfiting?

过拟合是由于高方差引起的,高方差是由于参数太多,特征值过于敏感导致的,正则化能够减少参数数量,降低特征值敏感度,所以能阻止过拟合。

神经网络训练中的梯度消失与梯度爆炸

层数比较多的神经网络模型在训练时也是会出现一些问题的,其中就包括梯度消失问题(gradient vanishing problem)和梯度爆炸问题(gradient exploding problem)。梯度消失问题和梯度爆炸问题一般随着网络层数的增加会变得越来越明显。
例如,对于下图所示的含有3个隐藏层的神经网络,梯度消失问题发生时,接近于输出层的hidden layer 3等的权值更新相对正常,但前面的hidden layer 1的权值更新会变得很慢,导致前面的层权值几乎不变,仍接近于初始化的权值,这就导致hidden layer 1相当于只是一个映射层,对所有的输入做了一个同一映射,这是此深层网络的学习就等价于只有后几层的浅层网络的学习了。

"grad"

而这种问题为何会产生呢?以下图的反向传播为例(假设每一层只有一个神经元且对于每一层
"equation"
"sigmoid"
可以推导出:
"1"

而sigmoid的导数如下图:
"derivative"

"1"
其实梯度爆炸和梯度消失问题都是因为网络太深,网络权值更新不稳定造成的,本质上是因为梯度反向传播中的连乘效应。对于更普遍的梯度消失问题,可以考虑用ReLU激活函数取代sigmoid激活函数。另外,LSTM的结构设计也可以改善RNN中的梯度消失问题。

参考:神经网络训练中的梯度消失与梯度爆炸

传统机器学习考察点:

1、bias与variance的含义,并结合ensemble method问哪种方法降低bias,哪种方法降低variance
2、lr与svm的区别与联系
3、gbdt与adaboost的区别与联系
4、手推svm,svm麻雀虽小五脏俱全
5、pca与lda的区别与联系,并推导
6、白化的原理与作用
7、给一个算法,例如lr,问这个算法的model、evaluate、optimization分别是啥

深度学习考察点

1、手推bp
2、梯度消失/爆炸原因,以及解决方法
3、bn的原理,与白化的联系
4、防止过拟合有哪些方法
5、dnn、cnn、rnn的区别与联系
6、机器学习与深度学习的联系
7、batch size大小会怎么影响收敛速度

CNN最成功的应用是在CV,那为什么NLP和Speech的很多问题也可以用CNN解出来?为什么AlphaGo里也用了CNN?这几个不相关的问题的相似性在哪里?CNN通过什么手段抓住了这个共性?

以上几个不相关问题的相关性在于,都存在局部与整体的关系,由低层次的特征经过组合,组成高层次的特征,并且得到不同特征之间的空间相关性。如下图:低层次的直线/曲线等特征,组合成为不同的形状,最后得到汽车的表示。
"cnn"
CNN抓住此共性的手段主要有四个:局部连接/权值共享/池化操作/多层次结构
局部连接使网络可以提取数据的局部特征;权值共享大大降低了网络的训练难度,一个Filter只提取一个特征,在整个图片(或者语音/文本) 中进行卷积;池化操作与多层次结构一起,实现了数据的降维,将低层次的局部特征组合成为较高层次的特征,从而对整个图片进行表示。

对所有优化问题来说, 有没有可能找到比現在已知算法更好的算法?

没有免费的午餐定理
"launch"

  • 对于训练样本(黑点),不同的算法A/B在不同的测试样本(白点)中有不同的表现,这表示:对于一个学习算法A,若它在某些问题上比学习算法 B更好,则必然存在一些问题,在那里B比A好。
  • 也就是说:对于所有问题,无论学习算法A多聪明,学习算法 B多笨拙,它们的期望性能相同。
  • 但是:没有免费午餐定力假设所有问题出现几率相同,实际应用中,不同的场景,会有不同的问题分布,所以,在优化算法时,针对具体问题进行分析,是算法优化的核心所在