• 深度学习面试问题总结


    在此记录下常见的深度学习面试问题。

    softmax函数导数的推导

    softmax用于多分类过程中,它将多个神经元的输出,映射到(0,1)区间内,可以看成概率来理解。softmax就是将原来输出通过softmax函数一作用,就映射成为(0,1)的值,而这些值的累和为1(满足概率的性质),那么我们就可以将它理解成概率,在最后选取输出结点的时候,我们就可以选取概率最大(也就是值对应最大的)结点,作为我们的预测目标。
    假设我们有一个数组(V)(V_i)表示(V)中的第(i)个元素,那么这个元素的softmax值就是:

    [S_i = frac{e^{V_i}}{sum_k e^{V_k}} ]

    假设我们使用交叉熵损失函数:

    [C=-sum_i y_i ln a_i ]

    其中,(y_i)表示真实的分类结果,表示softmax第i个输出值。
    我们要求的是loss对于神经元输出((z_i))的梯度,即:

    [frac{partial C}{partial z_i} ]

    根据复合函数求导法则,可得:

    [frac{partial C}{partial z_i} = frac{partial C}{partial a_j} frac{partial a_j}{partial z_i} ]

    其中:

    [frac{partial C}{partial a_j} = -sum_j y_j frac{1}{a_j} ]

    针对(frac{partial a_j}{partial z_i}),将其分为两种情况,
    (i=j):

    [frac{partial a_i}{partial z_i}=frac{partial frac{e^{z_i}}{sum_k e^{z_k}}}{partial z_i}=frac{e^{z_i}sum_k e^{z_k} - (e^{z_i})^2}{(sum_k e^{z_k})^2}=frac{e^{z_i}}{sum_k e^{z_k}}(1-frac{e^{z_i}}{sum_k e^{z_k}})=a_i (1-a_i) ]

    (i eq j)

    [frac{partial a_j}{partial z_i}=frac{partial frac{e^{z_j}}{sum_k e^{z_k}}}{partial z_i}=-e^{z_j}(frac{1}{sum_k e^{z_k}})^2 e^{z_i}=-a_i a_j ]

    故,

    [frac{partial C}{partial z_i}= -sum_j y_j frac{1}{a_j} (frac{partial a_j}{partial z_i})=-frac{y_i}{a_i}(a_i(1-a_i))+sum_{j eq i }frac{y_j}{a_j}a_i a_j = -y_i + y_i a_i +sum_{j eq i}y_j a_i \ =-y_i+a_i sum_j y_j =a_i - y_i ]

    什么是过拟合?深度学习解决过拟合的方法有哪些

    过拟合即在训练误差很小,而泛化误差很大,因为模型可能过于的复杂,使其”记住”了训练样本,然而其泛化误差却很高

    1. 加入正则化项,参数范数惩罚
      最常用的范数惩罚为L1,L2正则化,L1又被成为Lasso:
    2. 数据增强,增加样本数据量
    3. 提前终止(early stopping)
      模型在验证集上的误差在一开始是随着训练集的误差的下降而下降的。当超过一定训练步数后,模型在训练集上的误差虽然还在下降,但是在验证集上的误差却不在下降了。此时我们的模型就过拟合了。因此我们可以观察我们训练模型在验证集上的误差,一旦当验证集的误差不再下降时,我们就可以提前终止我们训练的模型。
    4. 参数绑定与参数共享
      在卷积神经网络CNN中,卷积层就是其中权值共享的方式,一个卷积核通过在图像上滑动从而实现共享参数,大幅度减少参数的个数,用卷积的形式是合理的,
    5. bagging 和其他集成方法
    6. Dropout
    7. 辅助分类节点(auxiliary classifiers)
      在Google Inception V1中,采用了辅助分类节点的策略,即将中间某一层的输出用作分类,并按一个较小的权重加到最终的分类结果中,这样相当于做了模型的融合,同时给网络增加了反向传播的梯度信号,提供了额外的正则化的思想.
    8. Batch Normalization
      BN在训练某层时,会对每一个mini-batch数据进行标准化(normalization)处理,使输出规范到N(0,1)的正太分布,减少了Internal convariate shift(内部神经元分布的改变),传统的深度神经网络在训练是,每一层的输入的分布都在改变,因此训练困难,只能选择用一个很小的学习速率,但是每一层用了BN后,可以有效的解决这个问题,学习速率可以增大很多倍.

    深度模型参数调整的一般方法论?

    重要性:学习率>正则值>dropout
    学习率:0.001,0.01,0.1,1,10 …….以10为阶数尝试
    小数据集上合适的参数大数据集上一般不会差,可以先减少训练类别。
    欠拟合:
    表现形式:训练集,测试集准确率都很低
    解决办法:增加网络层数,增加节点数,减少dropout值,减少L2正则值等等

    过拟合:
    表现形式:训练集准确率较高,测试集准确率比较低
    解决办法:增加数据、数据增强、参数范数惩罚L1、L2、提前终止、增加dropout值、BatchNormalization

    简述了解的优化器,发展综述

    • Momentum
      Momentum算法借用了物理中的动量概念,它模拟的是物体运动时的惯性,即更新的时候在一定程度上保留之前更新的方向,同时利用当前batch的梯度微调最终的更新方向。这样一来,可以在一定程度上增加稳定性,从而学习地更快,并且还有一定摆脱局部最优的能力
      为了防止波动,取前几次波动的平均值当做这次的W。用到理论的计算梯度的指数加权平均数,引进超参数beta(一般取0.9)
      beta的值越大,数据越平稳。但是beta的值过大会使数据有一种“滞后”的感觉

    [V_{dW} = eta V_{dW} + (1-eta) dW \ W = W-alpha V_{dW} ]

    • AdaGrad
      通常,我们在每一次更新参数时,对于所有的参数使用相同的学习率。而AdaGrad算法的思想是:每一次更新参数时(一次迭代),不同的参数使用不同的学习率。其中 (ε) 一般默认取 10−7,学习率$ α$一般取值为 0.01

    [G_t = G_{t-1}+g_t^2 \ heta_{t+1}= heta_t - frac{alpha}{sqrt{G_t}+epsilon} cdot g_t ]

    从公式中我们能够发现:
    优点:对于梯度较大的参数,(G_t)相对较大,则(frac{alpha}{sqrt{G_t}+epsilon})较小,意味着学习率会变得较小。而对于梯度较小的参数,则效果相反。这样就可以使得参数在平缓的地方下降的稍微快些,不至于徘徊不前。
    缺点:由于是累积梯度的平方,到后面 (G_t) 累积的比较大,会导致梯度 (frac{alpha}{sqrt{G_t}+epsilon} ightarrow 0),导致梯度消失。

    • RMSprop
      RMSprop,全称root mean square prop。也用到权重超参数beta(一般取0.999),和Momentum相似
      RMSprop也是对Adagrad的扩展,以在非凸的情况下效果更好。和Adadelta一样,RMSprop使用指数加权平均(指数衰减平均)只保留过去给定窗口大小的梯度,使其能够在找到凸碗状结构后快速收敛。

    [S_{dW} = ho S_{dW} + (1- ho) (dW)^2 \ W = W-alpha frac{dW}{sqrt{S_{dW}}+epsilon} ]

    同样 (ε)是为了防止分母为0,默认值设为$ 1e^{-6}$ 。$β $ 默认值设为$ 0.9$,学习率 (alpha)默认值设为$ 0.001$。

    • Adam
      Adam实际上是把momentum和RMSprop结合起来的一种算法。

    [V_{dW} = eta_1 V_{dW} + (1-eta_1) dW \ S_{dW} = eta_2 S_{dW} + (1-eta_2) (dW)^2 \ V_{dW}^{correct}=frac{V_{dW}}{1-eta_1^t} \ S_{dW}^{correct}=frac{S_{dW}}{1-eta_2^t} \ W = W-alpha frac{V_{dW}^{correct}}{sqrt{S_{dW}^{correct}}+epsilon} ]

    几个参数推荐的默认值分别为:(α=0.001,β1=0.9,β2=0.999,ε=10−8α=0.001,β1=0.9,β2=0.999,ε=10−8)

    模型网络对称性的问题

    如果参数都很大,那么经过wx+b这个线性函数时,输出的值也会很大,若是经过tanh/sigmoid激活函数,输出的结果绝对值都几乎接近于1,也就是说每个神经元的输出都几乎相同,这完全违背了神经网络的初衷,事实上我们希望每个神经网络都能去学习一个不同的特征,他们的输出值应该是有差异的。
    如果w值设置地太小了,经过线性函数wx+b的时候,wx可以忽略不计,于是线性函数的输出都约等于b,经过激活函数后的输出也几乎相同,又造成了神经元彼此雷同。

    模型参数初始化

    初始化的基本思想:方差不变,即设法对权值进行初始化,使得各层神经元的方差保持不变。参数初始化可能导致梯度消失或爆炸,所以基本原则是确保每一层的权重矩阵的方差都近似为 1。
    1)为网络中的所有连接权值赋上一个服从均值为0,标准差为0.01的正态分布的一个随机数。为第二、四、五层的卷积层和所有的全连接层神经元的偏置都赋予1的初始值,而其他层神经元的偏置均为0。这种初始化方法在模型的训练初期,能够有效的提速。因为为ReLU输入的都是正值。
    2)Xavier初始化
      从高斯分布或均匀分布中对权值进行采样,使得权值的方差是1/n,其中n是输入神经元的个数。该推导假设激活函数是线性的。
      Xavier,就是让我们每一层的输入(也是上一层的输出)都能控制一定范围内,这样就不会在激活函数那一块产生太多的问题,也不会导致梯度太小。Xavier初始化假设我们的数据(即xx)都是遵循一定的分布(其实统计学不是很懂,但很多理念都建构在这个基础上),然后让我们的权重(ww)遵循的分布跟它相乘后(即ff)满足一定的条件。如果样本空间与类别空间的分布差异很大,比如说类别空间特别稠密,样本空间特别稀疏辽阔,那么在类别空间得到的用于反向传播的误差丢给样本空间后简直变得微不足道,也就是会导致模型的训练非常缓慢。同样,如果类别空间特别稀疏,样本空间特别稠密,那么在类别空间算出来的误差丢给样本空间后简直是爆炸般的存在,即导致模型发散震荡,无法收敛。因此,我们要让样本空间与类别空间的分布差异(密度差别)不要太大,也就是要让它们的方差尽可能相等。
    3)He初始化/MSRA初始化
      从高斯分布或均匀分布中对权值进行采样,使得权值的方差是2/n。该推导假设激活函数是ReLU。因为ReLU会将小于0的神经元置零,大致上会使一半的神经元置零,所以为了弥补丢失的这部分信息,方差要乘以2。
    4)批量规范化(batch-normalization,BN)
      每层显式地对神经元的激活值做规范化,使其具有零均值和单位方差。批量规范化使激活值的分布固定下来,这样可以使各层更加独立地进行学习。批量规范化可以使得网络对初始化和学习率不太敏感。此外,批量规范化有些许正则化的作用,但不要用其作为正则化手段。

    深度模型参数调整的一般方法论?

    重要性:学习率>正则值>dropout
    学习率:0.001,0.01,0.1,1,10 …….以10为阶数尝试
    小数据集上合适的参数大数据集上一般不会差,可以先减少训练类别。
    欠拟合:
    表现形式:训练集,测试集准确率都很低
    解决办法:增加网络层数,增加节点数,减少dropout值,减少L2正则值等等

    过拟合:
    表现形式:训练集准确率较高,测试集准确率比较低
    解决办法:增加数据、数据增强、参数范数惩罚L1、L2、提前终止、增加dropout值、BatchNormalization

    如何减少参数

    权值共享、VGG的感受野、GoogLeNet的inception
    CNN中减少网络的参数的三个思想:
    1) 局部连接(Local Connectivity)
    每个神经元没有必要对全局图像进行感知,只需要对局部进行感知,然后在更高层将局部的信息综合起来就得到了全局的信息。
    2) 权值共享(Shared Weights)
    对于同一个卷积核,它在一个区域提取到的特征,也能适用于于其他区域。在一个卷积核的情况下,进行权值共享。
    3) 池化(Pooling)
    池化一般分为max pooling和average pooling。定义池化窗口,最大池化为取窗口中最大的那个值,平均池化为取窗口中所有数的平均值。
    1x1卷积核 inception
    1x1的卷积核可以进行降维或者升维,也就是通过控制卷积核(通道数)实现,这个可以帮助减少模型参数,也可以对不同特征进行尺寸的归一化;同时也可以用于不同channel上特征的融合。一个trick就是在降维的时候考虑结合传统的降维方式,如PCA的特征向量实现,这样效果也可以得到保证。

    梯度消失和梯度爆炸及解决办法

    在深度神经网络中的梯度是不稳定的,在靠近输入层的隐藏层中或会消失,或会爆炸。
    梯度不稳定的原因:根据链式求导法则,前面层上的梯度是来自后面层上梯度的乘积。当存在过多的层时,就会出现梯度不稳定场景,比如梯度消失和梯度爆炸。

    如何解决梯度消失和梯度爆炸

    梯度消失和梯度爆炸问题都是因为网络太深,网络权值更新不稳定造成的,本质上是因为梯度反向传播中的连乘效应。对于更普遍的梯度消失问题,可以考虑一下三种方案解决:

    1. 用ReLU、Leaky-ReLU、P-ReLU、R-ReLU、Maxout等替代sigmoid函数。
    2. 用Batch Normalization。
    3. LSTM的结构设计也可以改善RNN中的梯度消失问题。

    Dropout为何能防止过拟合?

    Dropout是指在深度学习网络的训练过程中,对于神经网络单元,按照一定的概率将其暂时从网络中丢弃。由于是随机丢弃,故而每一个mini-batch都在训练不同的网络。
    Dropout可以被认为是集成非常多的大神经 网络的实用Bagging方法,防止参数过分依赖训练数据,增加参数对数据集的泛化能力。在学习阶段,以概率p主动临时性地忽略掉部分隐藏节点。这一操作的好处在于,在较大程度上减小了网络的大小,而在这个“残缺”的网络中,让神经网络学习数据中的局部特征(即部分分布式特征)。
    在测试阶段,将参与学习的节点和那些被隐藏的节点以一定的概率p加权求和,综合计算得到网络的输出。

    BatchNorm原理

    BatchNorm对于每个隐层神经元,把逐渐向非线性函数映射后向取值区间极限饱和区靠拢的输入分布强制拉回到均值为0方差为1的比较标准的正态分布,使得非线性变换函数的输入值落入对输入比较敏感的区域,以此避免梯度消失问题。BN为了保证非线性的获得,对变换后的满足均值为0方差为1的x又进行了scale加上shift操作(y=scale*x+shift),每个神经元增加了两个参数scale和shift参数。
    BN 的论文指出,传统的深度神经网络在训练时,每一层的输入的分布都在变化,导致训练变得困难,我们只能使用一个很小的学习速率解决这个问题。而对每一层使用 BN 之后,我们就可以有效地解决这个问题,学习速率可以增大很多倍,达到之前的准确率所需要的迭代次数只有1/14,训练时间大大缩短。BN 某种意义上还起到了正则化的作用,所以可以减少或者取消 Dropout 和 LRN,简化网络结构。

    常用的几个模型

    LeNet5 –没啥特点-不过是第一个CNN应该要知道
    AlexNet 引入了ReLU和dropout,引入数据增强、池化相互之间有覆盖,三个卷积一个最大池化+三个全连接层
    VGGNet 采用11和33的卷积核以及2*2的最大池化使得层数变得更深。常用VGGNet-16和VGGNet19
    Google Inception Net
      1、去除了最后的全连接层,而是用一个全局的平均池化来取代它;
      2、引入Inception Module,这是一个4个分支结合的结构。所有的分支都用到了(1*1)的卷积,这是因为(1*1)可以用很少的参数达到非线性和特征变换。
      3、Inception V2第二版将所有的(5*5)变成2个(3*3),而且提出了Batch Normalization;
      4、Inception V3第三版就更变态了,把较大的二维卷积拆成了两个较小的一维卷积,加速运算、减少过拟合,同时还更改了Inception Module的结构。
    微软ResNet残差神经网络(Residual Neural Network) 1、引入高速公路结构,可以让神经网络变得非常深
    2、ResNet第二个版本将ReLU激活函数变成y=x的线性函数

    CNN卷积-inception网络构造与历史

    早期的V1 结构借鉴了 NIN 的设计思路,对网络中的传统卷积层进行了修改,针对限制深度神经网络性能的主要问题,一直不断改进延伸到 V4:
    参数空间大,容易过拟合,且训练数据集有限;
    网络结构复杂,计算资源不足,导致难以应用;
    深层次网络结构容易出现梯度弥散,模型性能下降。

    GoogLeNet 对网络中的传统卷积层进行了修改,提出了被称为 Inception 的结构,用于增加网络深度和宽度,提高深度神经网络性能。
    Inception V1
    主要考虑多个不同 size 的卷积核能够增强网络的适应力,paper 中分别使用(1*1)(3*3)(5*5)卷积核,同时加入(3*3) max pooling。
    每一层 Inception module 的 filters 参数量为所有分支上的总数和,多层 Inception 最终将导致 model 的参数数量庞大,对计算资源有更大的依赖。

    Inception V2 学习了 VGG 用两个(3*3)的卷积代替(5*5)的大卷积,在降低参数的同时建立了更多的非线性变换,使得 CNN 对特征的学习能力更强:
    另外提出了著名的 Batch Normalization(以下简称BN)方法。BN 是一个非常有效的正则化方法,可以让大型卷积网络的训练速度加快很多倍,同时收敛后的分类准确率也可以得到大幅提高。BN 在用于神经网络某层时,会对每一个 mini-batch 数据的内部进行标准化(normalization)处理,使输出规范化到 N(0,1) 的正态分布,减少了 Internal Covariate Shift(内部神经元分布的改变)。

    Inception V3
    一是引入了 Factorization into small convolutions 的思想,将一个较大的二维卷积拆成两个较小的一维卷积,比如将7´7卷积拆成1´7卷积和7´1卷积,或者将3´3卷积拆成1´3卷积和3´1卷积,一方面节约了大量参数,加速运算并减轻了过拟合(比将7´7卷积拆成1´7卷积和7´1卷积,比拆成3个3´3卷积更节约参数),同时增加了一层非线性扩展模型表达能力。
    这种非对称的卷积结构拆分,其结果比对称地拆为几个相同的小卷积核效果更明显,可以处理更多、更丰富的空间特征,增加特征多样性。
    另一方面,Inception V3 优化了 Inception Module 的结构,在 Inception Module 有35´35、17´17和8´8三种不同结构。这些 Inception Module 只在网络的后部出现,前部还是普通的卷积层。并且 Inception V3 除了在 Inception Module 中使用分支,还在分支中使用了分支(8´8的结构中),

    Inception V4
    Inception V4 相比 V3 主要是结合了微软的 ResNet,将错误率进一步减少

    总结
    Inception V1——构建了1x1、3x3、5x5的 conv 和3x3的 pooling 的分支网络,同时使用 MLPConv 和全局平均池化,扩宽卷积层网络宽度,增加了网络对尺度的适应性;
    Inception V2——提出了 Batch Normalization,代替 Dropout 和 LRN,其正则化的效果让大型卷积网络的训练速度加快很多倍,同时收敛后的分类准确率也可以得到大幅提高,同时学习 VGG 使用两个3´3的卷积核代替5´5的卷积核,在降低参数量同时提高网络学习能力;
    Inception V3——引入了 Factorization,将一个较大的二维卷积拆成两个较小的一维卷积,比如将3´3卷积拆成1´3卷积和3´1卷积,一方面节约了大量参数,加速运算并减轻了过拟合,同时增加了一层非线性扩展模型表达能力,除了在 Inception Module 中使用分支,还在分支中使用了分支(Network In Network In Network);
    Inception V4——研究了 Inception Module 结合 Residual Connection,结合 ResNet 可以极大地加速训练,同时极大提升性能,在构建 Inception-ResNet 网络同时,还设计了一个更深更优化的 Inception v4 模型,能达到相媲美的性能

    给定卷积核的尺寸,特征图大小计算方法?

    卷积中的特征图大小计算方式有两种,分别是‘VALID’和‘SAME’。
    如果计算方式采用'VALID',则:

    [w_{out} = frac{w_{in}-F}{stride}+1 ]

    其中({w_{out}})为输出特征图的大小,({w_{in}})为输入特征图的大小,F为卷积核大小,stride为卷积步长。
    如果计算方式采用'SAME',输出特征图的大小与输入特征图的大小保持不变,

    [w_{out} = frac{w_{in}+2*padding-F}{stride}+1 ]

    其中padding为特征图填充的圈数。

    请简要介绍下Tensorflow的计算图。

    Tensorflow是一个通过计算图的形式来表述计算的编程系统,计算图也叫数据流图,可以把计算图看做是一种有向图,Tensorflow中的每一个计算都是计算图上的一个节点,而节点之间的边描述了计算之间的依赖关系。

    神经网络不收敛不学习的原因

    1、没有对数据进行归一化
    2、忘记检查输入和输出
    3、没有对数据进行预处理
    4、没有对数据正则化
    5、使用过大的样本
    6、使用不正确的学习率
    7、在输出层使用错误的激活函数
    8、网络中包含坏梯度
    9、初始化权重错误
    10、过深的网络
    11、隐藏单元数量错误
    12、优化算法不对,一般用adam居多。
    13、数据随机性太强,同时网络结构太复杂(样本空间太大,同时样本数量不够,网络函数空间也大)
    14、学习率过大。网络可能快要收敛了,却忽然在下一个epoch走向了错误的方向,最终导致不收敛。

    可以归结为数据、网络、优化算法(算法、学习率)三方面。

  • 相关阅读:
    好的开源项目汇总
    强制SVN上传代码时添加日志
    微信开发-回调模式
    Struct2中自定义的Filter无效
    Ajax 传包含集合的JSON
    PostgreSQL数据库PL/PGSQL学习使用
    单用户对比PG 9.5.4和SYBASE 15.7对超大表的操作性能
    一场一波三折的SQL优化经历
    聚簇索引对数据插入的影响
    磁盘IO初探
  • 原文地址:https://www.cnblogs.com/hellojamest/p/11178803.html
Copyright © 2020-2023  润新知