在此记录下常见的深度学习面试问题.
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 \neq 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 \neq i }\frac{y_j}{a_j}a_i a_j = -y_i + y_i a_i +sum_{j \neq i}y_j a_i \=-y_i+a_i \sum_j y_j =a_i - y_i \]
什么是过拟合? 深度学习解决过拟合的方法有哪些
过拟合即在训练误差很小, 而泛化误差很大, 因为模型可能过于的复杂, 使其 "记住" 了训练样本, 然而其泛化误差却很高
加入正则化项, 参数范数惩罚
最常用的范数惩罚为 L1,L2 正则化, L1 又被成为 Lasso:
数据增强, 增加样本数据量
提前终止(early stopping)
模型在验证集上的误差在一开始是随着训练集的误差的下降而下降的. 当超过一定训练步数后, 模型在训练集上的误差虽然还在下降, 但是在验证集上的误差却不在下降了. 此时我们的模型就过拟合了. 因此我们可以观察我们训练模型在验证集上的误差, 一旦当验证集的误差不再下降时, 我们就可以提前终止我们训练的模型.
参数绑定与参数共享
在卷积神经网络 CNN 中, 卷积层就是其中权值共享的方式, 一个卷积核通过在图像上滑动从而实现共享参数, 大幅度减少参数的个数, 用卷积的形式是合理的,
bagging 和其他集成方法
Dropout
辅助分类节点(auxiliary classifiers)
在 Google Inception V1 中, 采用了辅助分类节点的策略, 即将中间某一层的输出用作分类, 并按一个较小的权重加到最终的分类结果中, 这样相当于做了模型的融合, 同时给网络增加了反向传播的梯度信号, 提供了额外的正则化的思想.
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
- } = \beta V_{
- dW
- } + (1-\beta) dW \W = W-\alpha V_{
- dW
- } \]
- AdaGrad
通常, 我们在每一次更新参数时, 对于所有的参数使用相同的学习率. 而 AdaGrad 算法的思想是: 每一次更新参数时(一次迭代), 不同的参数使用不同的学习率. 其中 \(ε\) 一般默认取 10?7, 学习率 $ α$ 一般取值为 0.01
\[ G_t = G_{t-1}+g_t^2 \\theta_{t+1}=\theta_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} \rightarrow 0\), 导致梯度消失.
RMSprop
RMSprop, 全称 root mean square prop. 也用到权重超参数 beta(一般取 0.999), 和 Momentum 相似
RMSprop 也是对 Adagrad 的扩展, 以在非凸的情况下效果更好. 和 Adadelta 一样, RMSprop 使用指数加权平均 (指数衰减平均) 只保留过去给定窗口大小的梯度, 使其能够在找到凸碗状结构后快速收敛.
\[ S_{dW} = \rho S_{dW} + (1-\rho) (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} = \beta_1 V_{dW} + (1-\beta_1) dW \S_{dW} = \beta_2 S_{dW} + (1-\beta_2) (dW)^2 \V_{dW}^{correct}=\frac{V_{dW}}{1-\beta_1^t} \S_{dW}^{correct}=\frac{S_{dW}}{1-\beta_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 的特征向量实现, 这样效果也可以得到保证.
梯度消失和梯度爆炸及解决办法
在深度神经网络中的梯度是不稳定的, 在靠近输入层的隐藏层中或会消失, 或会爆炸.
梯度不稳定的原因: 根据链式求导法则, 前面层上的梯度是来自后面层上梯度的乘积. 当存在过多的层时, 就会出现梯度不稳定场景, 比如梯度消失和梯度爆炸.
如何解决梯度消失和梯度爆炸
梯度消失和梯度爆炸问题都是因为网络太深, 网络权值更新不稳定造成的, 本质上是因为梯度反向传播中的连乘效应. 对于更普遍的梯度消失问题, 可以考虑一下三种方案解决:
用 ReLU,Leaky-ReLU,P-ReLU,R-ReLU,Maxout 等替代 sigmoid 函数.
用 Batch Normalization.
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 走向了错误的方向, 最终导致不收敛.
可以归结为数据, 网络, 优化算法 (算法, 学习率) 三方面.
来源: http://www.bubuko.com/infodetail-3121992.html