(一)深度学习基础部分面试题

一些总结比较好的链接:

https://blog.csdn.net/woaidapaopao/article/details/77806273

1、请简要介绍下tensorflow的计算图

答:计算图是一张有节点有方向的数据流图,每一个节点都是一个张量,每个节点之间的边描述了计算之间的依赖关系和数学操作

2、你有哪些深度学习(rnn、cnn)调参的经验?

https://www.julyedu.com/question/big/kp_id/26/ques_id/998

3、Sigmoid、Tanh、ReLu这三个激活函数有什么缺点或不足,有没改进的激活函数。

答:sigmoid:缺点:若激活值很大的时候或者很小,激活函数在其区域梯度很小使得训练速度很慢 Tanh:缺点:同上,优点:数据类似于集中于零左右, relu缺点:在零的时候不可导,若激活值小于零,梯度为零,使得训练速度很慢,不过这种情况很少发生,有足够多的神经元使得其z值大于零; 改进:采用含虚弱的relu激活函数,即若小于零时,也让其有点梯度。比如小于零时,激活函数为:0.01Z。

4、为什么引入非线性激励函数?

答:激励函数可以给神经网络引入非线性因素,可以把当前特征空间映射到其他空间,使其几乎能拟合现实中任何问题,增加网络的能力。

第一,对于神经网络来说,网络的每一层相当于f(wx+b)=f(w'x),对于线性函数,其实相当于f(x)=x,那么在线性激活函数下,每一层相当于用一个矩阵去乘以x,那么多层就是反复的用矩阵去乘以输入。
根据矩阵的乘法法则,多个矩阵相乘得到一个大矩阵。所以线性激励函数下,多层网络与一层网络相当。比如,两层的网络f(W1*f(W2x))=W1W2x=Wx。 第二,非线性变换是深度学习有效的原因之一。原因在于非线性相当于对空间进行变换,变换完成后相当于对问题空间进行简化,原来线性不可解的问题现在变得可以解了。 下图可以很形象的解释这个问题,左图用一根线是无法划分的。经过一系列变换后,就变成线性可解的问题了。
其实很像SVM中的核函数(如高斯核函数)

如果不用激励函数(其实相当于激励函数是f(x) = x),在这种情况下你每一层输出都是上层输入的线性函数,很容易验证,无论你神经网络有多少层,输出都是输入的线性组合,与没有隐藏层效果相当,这种情况就是最原始的感知机(Perceptron)了。

正因为上面的原因,我们决定引入非线性函数作为激励函数,这样深层神经网络就有意义了(不再是输入的线性组合,可以逼近任意函数)。最早的想法是sigmoid函数或者tanh函数,输出有界,很容易充当下一层输入(以及一些人的生物解释)。

5、
什麽样的资料集不适合用深度学习?
1、数据集太小,数据样本不足时,深度学习相对其它机器学习算法,没有明显优势。

2、数据集没有局部相关特性,目前深度学习表现比较好的领域主要是图像/语音/自然语言处理等领域,这些领域的一个共性是局部相关性。图像中像素组成物体,语音信号中音位组合成单词,文本数据中单词组合成句子,这些特征元素的组合一旦被打乱,表示的含义同时也被改变。
对于没有这样的局部相关性的数据集,不适于使用深度学习算法进行处理。
举个例子:预测一个人的健康状况,相关的参数会有年龄、职业、收入、家庭状况等各种元素,将这些元素打乱,并不会影响相关的结果。
6、如何解决梯度消失和梯度膨胀
(1)梯度消失:
根据链式法则,如果每一层神经元对上一层的输出的偏导乘上权重结果都小于1的话,那么即使这个结果是0.99,在经过足够多层传播之后,误差对输入层的偏导会趋于0
可以采用ReLU激活函数有效的解决梯度消失的情况,也可以用Batch Normalization解决这个问题。关于深度学习中 Batch Normalization为什么效果好?参见:https://www.zhihu.com/question/38102762

(2)梯度膨胀
根据链式法则,如果每一层神经元对上一层的输出的偏导乘上权重结果都大于1的话,在经过足够多层传播之后,误差对输入层的偏导会趋于无穷大
可以通过激活函数来解决,或用Batch Normalization解决这个问题。

补充:
批归一化(Batch Normalization)
https://www.cnblogs.com/skyfsm/p/8453498.html
 
7、请简述神经网络的发展史。
sigmoid会饱和,造成梯度消失。于是有了ReLU。
ReLU负半轴是死区,造成梯度变0。于是有了LeakyReLU,PReLU。
强调梯度和权值分布的稳定性,由此有了ELU,以及较新的SELU。
太深了,梯度传不下去,于是有了highway。
干脆连highway的参数都不要,直接变残差,于是有了ResNet。

强行稳定参数的均值和方差,于是有了BatchNorm。
在梯度流中增加噪声,于是有了 Dropout。
RNN梯度不稳定,于是加几个通路和门控,于是有了LSTM。
LSTM简化一下,有了GRU。
GAN的JS散度有问题,会导致梯度消失或无效,于是有了WGAN。
WGAN对梯度的clip有问题,于是有了WGAN-GP。

 8、神经网络中激活函数的真正意义?一个激活函数需要具有哪些必要的属性?还有哪些属性是好的属性但不必要的?

1. 非线性:即导数不是0。这个条件是多层神经网络的基础,保证多层网络不退化成单层线性网络。这也是激活函数的意义所在。

2. 几乎处处可微(可导):可微性保证了在优化中梯度的可计算性。传统的激活函数如sigmoid等满足处处可微。对于分段线性函数比如ReLU,只满足几乎处处可微(即仅在有限个点处不可微)。对于SGD算法来说,由于几乎不可能收敛到梯度接近零的位置,有限的不可微点对于优化结果不会有很大影响[1]。

3. 计算简单:非线性函数有很多。极端的说,一个多层神经网络也可以作为一个非线性函数,类似于Network In Network[2]中把它当做卷积操作的做法。但激活函数在神经网络前向的计算次数与神经元的个数成正比,因此简单的非线性函数自然更适合用作激活函数。这也是ReLU之流比其它使用Exp等操作的激活函数更受欢迎的其中一个原因。

4. 非饱和性(saturation):饱和指的是在某些区间梯度接近于零(即梯度消失),使得参数无法继续更新的问题。最经典的例子是Sigmoid,它的导数在x为比较大的正值和比较小的负值时都会接近于0。更极端的例子是阶跃函数,由于它在几乎所有位置的梯度都为0,因此处处饱和,无法作为激活函数。ReLU在x>0时导数恒为1,因此对于再大的正值也不会饱和。但同时对于x<0,其梯度恒为0,这时候它也会出现饱和的现象(在这种情况下通常称为dying ReLU)。Leaky ReLU[3]和PReLU[4]的提出正是为了解决这一问题。

5. 单调性(monotonic):即导数符号不变。这个性质大部分激活函数都有,除了诸如sin、cos等。个人理解,单调性使得在激活函数处的梯度方向不会经常改变,从而让训练更容易收敛。

6. 输出范围有限:有限的输出范围使得网络对于一些比较大的输入也会比较稳定,这也是为什么早期的激活函数都以此类函数为主,如Sigmoid、TanH。但这导致了前面提到的梯度消失问题,而且强行让每一层的输出限制到固定范围会限制其表达能力。因此现在这类函数仅用于某些需要特定输出范围的场合,比如概率输出(此时loss函数中的log操作能够抵消其梯度消失的影响[1])、LSTM里的gate函数。

7. 接近恒等变换(identity):即约等于x。这样的好处是使得输出的幅值不会随着深度的增加而发生显著的增加,从而使网络更为稳定,同时梯度也能够更容易地回传。这个与非线性是有点矛盾的,因此激活函数基本只是部分满足这个条件,比如TanH只在原点附近有线性区(在原点为0且在原点的导数为1),而ReLU只在x>0时为线性。这个性质也让初始化参数范围的推导更为简单[5][4]。额外提一句,这种恒等变换的性质也被其他一些网络结构设计所借鉴,比如CNN中的ResNet[6]和RNN中的LSTM。

8. 参数少:大部分激活函数都是没有参数的。像PReLU带单个参数会略微增加网络的大小。还有一个例外是Maxout[7],尽管本身没有参数,但在同样输出通道数下k路Maxout需要的输入通道数是其它函数的k倍,这意味着神经元数目也需要变为k倍;但如果不考虑维持输出通道数的情况下,该激活函数又能将参数个数减少为原来的k倍。

9. 归一化(normalization):这个是最近才出来的概念,对应的激活函数是SELU[8],主要思想是使样本分布自动归一化到零均值、单位方差的分布,从而稳定训练。在这之前,这种归一化的思想也被用于网络结构的设计,比如Batch Normalization[9]。
9、简单说说CNN常用的几个模型

10、什么是梯度爆炸?来的的问题是?
w = w - lr*梯度
反向传播中,求导的链式法则,将梯度不断相乘相乘再相乘,如果都是>1的话,最后得到的梯度会很大,损失函数将会发散而不会收敛。
梯度的定义:
误差梯度是神经网络训练过程中计算的方向和数值,用于以正确的方向和合适的量更新网络权重。
梯度爆炸产生的原因:在深层网络或循环神经网络中,误差梯度可在更新中累积,变成非常大的梯度,然后导致网络权重的大幅更新,并因此使网络变得不稳定。
在极端情况下,权重的值变得非常大,以至于溢出,导致 NaN 值。网络层之间的梯度(值大于 1.0)重复相乘导致的指数级增长会产生梯度爆炸。

梯度爆炸带来的问题:
在深度多层感知机网络中,梯度爆炸会引起网络不稳定,最好的结果是无法从训练数据中学习,而最坏的结果是出现无法再更新的 NaN 权重值。
梯度爆炸导致学习过程不稳定。

在循环神经网络中,梯度爆炸会导致网络不稳定,无法利用训练数据学习,最好的结果是网络无法学习长的输入序列数据。

11、如何确定是否出现梯度爆炸?
训练过程中出现梯度爆炸会伴随一些细微的信号,如:
模型无法从训练数据中获得更新(如低损失)。
模型不稳定,导致更新过程中的损失出现显著变化。
训练过程中,模型损失变成 NaN。
如果你发现这些问题,那么你需要仔细查看是否出现梯度爆炸问题。

以下是一些稍微明显一点的信号,有助于确认是否出现梯度爆炸问题。
训练过程中模型梯度快速变大。
训练过程中模型权重变成 NaN 值。
训练过程中,每个节点和层的误差梯度值持续超过 1.0。

12、如何修复梯度爆炸问题?

1. 重新设计网络模型
在深度神经网络中,梯度爆炸可以通过重新设计层数更少的网络来解决。
使用更小的批尺寸对网络训练也有好处。
在循环神经网络中,训练过程中在更少的先前时间步上进行更新(沿时间的截断反向传播,truncated Backpropagation through time)可以缓解梯度爆炸问题。

2. 使用 ReLU 激活函数
在深度多层感知机神经网络中,梯度爆炸的发生可能是因为激活函数,如之前很流行的 Sigmoid 和 Tanh 函数。
使用 ReLU 激活函数可以减少梯度爆炸。采用 ReLU 激活函数是最适合隐藏层的新实践。

3. 使用长短期记忆网络
在循环神经网络中,梯度爆炸的发生可能是因为某种网络的训练本身就存在不稳定性,如随时间的反向传播本质上将循环网络转换成深度多层感知机神经网络。
使用长短期记忆(LSTM)单元和相关的门类型神经元结构可以减少梯度爆炸问题。
采用 LSTM 单元是适合循环神经网络的序列预测的最新最好实践。

4. 使用梯度截断(Gradient Clipping)
在非常深且批尺寸较大的多层感知机网络和输入序列较长的 LSTM 中,仍然有可能出现梯度爆炸。如果梯度爆炸仍然出现,你可以在训练过程中检查和限制梯度的大小。这就是梯度截断。
处理梯度爆炸有一个简单有效的解决方案:如果梯度超过阈值,就截断它们。
 ——《Neural Network Methods in Natural Language Processing》,2017.
具体来说,检查误差梯度的值是否超过阈值,如果超过,则截断梯度,将梯度设置为阈值。
梯度截断可以一定程度上缓解梯度爆炸问题(梯度截断,即在执行梯度下降步骤之前将梯度设置为阈值)。
     ——《深度学习》,2016.
在 Keras 深度学习库中,你可以在训练之前设置优化器上的 clipnorm 或 clipvalue 参数,来使用梯度截断。
默认值为 clipnorm=1.0 、clipvalue=0.5。详见:https://keras.io/optimizers/。

5. 使用权重正则化(Weight Regularization)
如果梯度爆炸仍然存在,可以尝试另一种方法,即检查网络权重的大小,并惩罚产生较大权重值的损失函数。该过程被称为权重正则化,通常使用的是 L1 惩罚项(权重绝对值)或 L2 惩罚项(权重平方)。
对循环权重使用 L1 或 L2 惩罚项有助于缓解梯度爆炸。
——On the difficulty of training recurrent neural networks,2013.
在 Keras 深度学习库中,你可以通过在层上设置 kernel_regularizer 参数和使用 L1 或 L2 正则化项进行权重正则化。








原文地址:https://www.cnblogs.com/kongweisi/p/10917659.html