机器学习、深度学习面试知识点汇总
本文总结了一些秋招面试中会遇到的问题和一些重要的知识点,适合面试前突击和巩固基础知识。
作者丨 Oldpan 来源丨 oldpan 博客 编辑丨极市平台
前言
最近这段时间正临秋招,这篇文章是老潘在那会找工作过程中整理的一些重要知识点,内容比较杂碎,部分采集于网络,简单整理下发出来,适合面试前突击,当然也适合巩固基础知识。另外推荐大家一本叫做《百面机器学习》的新书,2018 年 8 月份出版的,其中包括了很多机器学习、深度学习面试过程中会遇到的问题,比较适合需要准备面试的机器学习、深度学习方面的算法工程师,当然也同样适合巩固基础~ 有时间一定要需要看的书籍:
程序员的数学系列,适合重温知识,回顾一些基础的线性代数、概率论。
深度学习花书,总结类书,有基础知识的讲解,比较全面。
统计学习方法,总结类书,篇幅不长,都是核心。
Pattern Recognition and Machine Learning,条理清晰,用贝叶斯的方式来讲解机器学习。
机器学习西瓜书,适合当教材,内容较广但是不深。
常见的常识题
L1 正则可以使少数权值较大,多数权值为 0,得到稀疏的权值;L2 正则会使权值都趋近于 0 但非零,得到平滑的权值;
在 AdaBoost 算法中,被错分的样本的权重更新比例的公式相同;
Boosting 和 Bagging 都是组合多个分类器投票的方法,但 Boosting 是根据单个分类器的正确率决定其权重,Bagging 是可简单地设置所有分类器权重相同;
EM 算法不能保证找到全局最优值;
SVR 中核函数宽度小欠拟合,宽度大容易过拟合
PCA 和 LDA 都是经典的降维算法。PCA 是无监督的,也就是训练样本不需要标签;LDA 是有监督的,也就是训练样本需要标签。PCA 是去除掉原始数据中冗余的维度,而 LDA 是寻找一个维度,使得原始数据在该维度上投影后不同类别的数据尽可能分离开来。
PCA 是一种正交投影,它的思想是使得原始数据在投影子空间的各个维度的方差最大。假设我们要将 N 维的数据投影到 M 维的空间上(M<N),根据 PCA,我们首先求出这 N 维数据的协方差矩阵,然后求出其前 M 个最大的特征值所对应的特征向量,那么这 M 个特征向量即为所求的投影空间的基。LDA 投影后类内方差最小,类间方差最大。如下图所示有两种投影方式,左边的投影后红色数据和蓝色数据还有重叠部分,右边的投影后红色数据和蓝色数据则刚好被分开。LDA 的投影即类似右边的投影方式,投影后使得不同类别的数据尽可能分开,而相同类别的数据则尽可能紧凑地分布。
参考链接:PCA 和 LDA 的对比
KNN K 近邻
关于 K 近邻算法的知识有很多,比如算法执行的步骤、应用领域以及注意事项,不过相信很多人对 K 近邻算法的使用注意事项不是很清楚。在这篇文章中我们针对这个问题进行解答,带大家来好好了解一下 k 近邻算法的注意事项以及 K 近邻算法的优点与缺点。
K 近邻算法的注意事项
K 近邻算法的使用注意事项具体就是使用距离作为度量时,要保证所有特征在数值上是一个数量级上,以免距离的计算被数量级大的特征所主导。在数据标准化这件事上,还要注意一点,训练数据集和测试数据集一定要使用同一标准的标准化。其中的原因总的来说就有两点内容,第一就是标准化其实可以视为算法的一部分,既然数据集都减去了一个数,然后除以一个数,这两个数对于所有的数据来说,就要一视同仁。第二就是训练数据集其实很少,在预测新样本的时候,新样本就更少得可怜,如果新样本就一个数据,它的均值就是它自己,标准差是 0,这根本就不合理。
K 近邻算法的优点是什么呢?
K 近邻算法的优点具体体现在四方面。第一就就是 k 近邻算法是一种在线技术,新数据可以直接加入数据集而不必进行重新训练,第二就是 k 近邻算法理论简单,容易实现。第三就是准确性高,对异常值和噪声有较高的容忍度。第四就是 k 近邻算法天生就支持多分类,区别与感知机、逻辑回归、SVM。
K 近邻算法的缺点是什么呢?
K 近邻算法的缺点,基本的 k 近邻算法每预测一个 “点” 的分类都会重新进行一次全局运算,对于样本容量大的数据集计算量比较大。而且 K 近邻算法容易导致维度灾难,在高维空间中计算距离的时候,就会变得非常远;样本不平衡时,预测偏差比较大,k 值大小的选择得依靠经验或者交叉验证得到。k 的选择可以使用交叉验证,也可以使用网格搜索。k 的值越大,模型的偏差越大,对噪声数据越不敏感,当 k 的值很大的时候,可能造成模型欠拟合。k 的值越小,模型的方差就会越大,当 k 的值很小的时候,就会造成模型的过拟合。
二维高斯核函数
如果让你写一个高斯模糊的函数,你该怎么写呢?
训练采样方法
交叉验证
留一法
自助法 (bootstrap):有放回的抽样方法,可能会抽到重复的样本
Kmean 和 GMM 原理、区别、应用场景
kmeans 的收敛性?
也可以看百面机器学习 P93、P102
如何在多台计算机上做 kmeans
其实是这样的,先分布到 n 台机器上,要保证 k 个初始化相同,经过一次迭代后,拿到 k*n 个新的 mean,放到一台新的机器上,因为初始化相同,所以 mean 的排列相同,然后对属于每个类的 n 个 mean 做加权平均,再放回每台机器上做下一步迭代。
KNN 算法以及流程
K 值的选择:
K 值较小,则模型复杂度较高,容易发生过拟合,学习的估计误差会增大,预测结果对近邻的实例点非常敏感。
K 值较大可以减少学习的估计误差,但是学习的近似误差会增大,与输入实例较远的训练实例也会对预测起作用,使预测发生错误,k 值增大模型的复杂度会下降。
在应用中,k 值一般取一个比较小的值,通常采用交叉验证法来来选取最优的 K 值。
KNN 中的 K 值选取对分类的结果影响至关重要,K 值选取的太小,模型太复杂。K 值选取的太大,导致分类模糊。那么 K 值到底怎么选取呢?有人用 Cross Validation,有人用贝叶斯,还有的用 bootstrap。而距离度量又是另外一个问题,比较常用的是选用欧式距离。可是这个距离真的具有普适性吗?《模式分类》中指出欧式距离对平移是敏感的,这点严重影响了判定的结果。在此必须选用一个对已知的变换(比如平移、旋转、尺度变换等)不敏感的距离度量。书中提出了采用切空间距离(tangent distance)来替代传统的欧氏距离。
无监督学习和有监督学习的区别
有监督:
感知机
K 近邻法
朴素贝叶斯
决策树
逻辑回归
支持向量机
提升方法
隐马尔科夫模型
条件随机场
无监督:
聚类 - kmeans
SVD 奇异值分解
PCA 主成分分析
生成式模型:LDA KNN 混合高斯 贝叶斯 马尔科夫 深度信念 判别式模型:SVM NN LR CRF CART
逻辑回归与 SVM 区别
逻辑回归即 LR。LR 预测数据的时候,给出的是一个预测结果为正类的概率,这个概率是通过 sigmoid 函数将 wTx 映射到 [0,1] 得到的,对于 wTx 正的很大时(可以认为离决策边界很远),得到为正类的概率趋近于 1;对于 wTx 负的很大时(可以认为离决策边界很远),得到为正类的概率趋近于 0。在 LR 中,跟 “与决策边界距离” 扯得上关系的仅此而已。在参数 w 求解过程中完全没有与决策边界距离的影子,所有样本都一视同仁。和感知机的不同之处在于,LR 用到与决策边界的距离,是用来给预测结果一个可以看得到的置信区间。感知机里面没有这一考虑,只根据符号来判断。而 SVM 更进一步,在参数的求解过程中,便舍弃了距离决策边界过远的点。LR 和感知机都很容易过拟合,只有 SVM 加入了 L2 范数之后的结构化风险最小化策略才解决了过拟合的问题。总结之:
感知机前后都没有引入与超平面 “距离” 的概念,它只关心是否在超平面的一侧;
LR 引入了距离,但是在训练模型求其参数的时候没有距离的概念,只是在最后预测阶段引入距离以表征分类的置信度;
SVM 两个地方有距离的概念:其一,在求超平面参数的时候有距离的概念,其表现为在与超平面一定距离内的点着重关注,而其他的一切点都不再关注。被关注的点称之为 “支撑向量”。其二,预测新样本的时候,和 LR 一样,距离代表置信度。
逻辑回归只能解决二分类问题,多分类用 softmax。相关参考链接
SVM和LR的区别与联系?
对非线性表达上,逻辑回归只能通过人工的特征组合来实现,而SVM可以很容易引入非线性核函数来实现非线性表达,淡然也可以通过特征组合。
逻辑回归产出的是概率值,而SVM只能产出是正类还是负类,不能产出概率。
逻辑回归的损失函数是log loss,而SVM使用的是hinge loss。
SVM主要关注的是“支持向量”,也就是和分类最相关的少数点,即关注局部关键信息;而逻辑回归是在全局进行优化的。这导致SVM天然比逻辑回归有更好的泛化能力,防止过拟合。
损失函数的优化方法不同,逻辑回归是使用梯度下降来求解对数似然函数的最优解;SVM使用SMO方法,来求解条件约束损失函数的对偶形式。
处理的数据规模不同。LR一般用来处理大规模的学习问题。如十亿级别的样本,亿级别的特征。(SVM是二次规划问题,需要计算m阶矩阵)
svm 更多的属于非参数模型,而logistic regression 是参数模型,本质不同。其区别就可以参考参数模型和非参模型的区别。
我们先来看一下SVM 和正则化的逻辑回归它们的损失函数:
bagging boosting 和 提升树
bagging 是通过结合几个模型降低泛化误差,分别训练几个不同的模型,然后让所有的模型表决测试样例的输出。模型平均奏效的原因是不同的模型通常不会在测试集上产生完全相同的误差。从原始样本集中抽取训练集. 每轮从原始样本集中使用 Bootstraping 的方法抽取 n 个训练样本(在训练集中,有些样本可能被多次抽取到,而有些样本可能一次都没有被抽中). 共进行 k 轮抽取,得到 k 个训练集.(k 个训练集相互独立)
Bagging 是并行的学习算法,思想很简单,即每一次从原始数据中根据均匀概率分布有放回的抽取和原始数据集一样大小的数据集合。样本点可以出现重复,然后对每一次产生的数据集构造一个分类器,再对分类器进行组合。对于分类问题,将上步得到的 k 个模型采用投票的方式得到分类结果;对回归问题,计算上述模型的均值作为最后的结果.
Boosting 是一族可将弱学习器提升为强学习器的算法. Boosting 的每一次抽样的样本分布是不一样的,每一次迭代,都是根据上一次迭代的结果,增加被错误分类的样本的权重。使模型在之后的迭代中更加注重难以分类的样本。这是一个不断学习的过程,也是一个不断提升的过程,这就是 Boosting 思想的本质所在。迭代之后,将每次迭代的基分类器进行集成,那么如何进行样本权重的调整和分类器的集成是我们需要考虑的关键问题。
Bagging 和 Boosting 的区别:
1)样本选择上:Bagging:训练集是在原始集中有放回选取的,从原始集中选出的各轮训练集之间是独立的. Boosting:每一轮的训练集不变,只是训练集中每个样例在分类器中的权重发生变化. 而权值是根据上一轮的分类结果进行调整.
2)样例权重:Bagging:使用均匀取样,每个样例的权重相等 Boosting:根据错误率不断调整样例的权值,错误率越大则权重越大.
3)预测函数:Bagging:所有预测函数的权重相等. Boosting:每个弱分类器都有相应的权重,对于分类误差小的分类器会有更大的权重.
4)并行计算:Bagging:各个预测函数可以并行生成 Boosting:各个预测函数只能顺序生成,因为后一个模型参数需要前一轮模型的结果.
Bagging 是 Bootstrap Aggregating 的简称,意思就是再取样 (Bootstrap) 然后在每个样本上训练出来的模型取平均,所以是降低模型的 variance. Bagging 比如 Random Forest 这种先天并行的算法都有这个效果。Boosting 则是迭代算法,每一次迭代都根据上一次迭代的预测结果对样本进行加权,所以随着迭代不断进行,误差会越来越小,所以模型的 bias 会不断降低 High variance 是 model 过于复杂 overfit,记住太多细节 noise,受 outlier 影响很大;high bias 是 underfit,model 过于简单,cost function 不够好。boosting 是把许多弱的分类器组合成一个强的分类器。弱的分类器 bias 高,而强的分类器 bias 低,所以说 boosting 起到了降低 bias 的作用。variance 不是 boosting 的主要考虑因素。bagging 是对许多强(甚至过强)的分类器求平均。在这里,每个单独的分类器的 bias 都是低的,平均之后 bias 依然低;而每个单独的分类器都强到可能产生 overfitting 的程度,也就是 variance 高,求平均的操作起到的作用就是降低这个 variance。Bagging 算法的代表:RandomForest 随机森林算法的注意点:
在构建决策树的过程中是不需要剪枝的。
整个森林的树的数量和每棵树的特征需要人为进行设定。
构建决策树的时候分裂节点的选择是依据最小基尼系数的。
咱们机器学习升级版的随机森林章节,我用白板写了写这个公式:p = 1 - (1 - 1/N)^N,其意义是:一个样本在一次决策树生成过程中,被选中作为训练样本的概率,当 N 足够大时,约等于 63.2%。简言之,即一个样本被选中的概率是 63.2%,根据二项分布的的期望,这意味着大约有 63.2% 的样本被选中。即有 63.2% 的样本是不重复的,有 36.8% 的样本可能没有在本次训练样本集中。随机森林是一个包含多个决策树的分类器,并且其输出的类别是由个别树输出的类别的众数而定。随机森林的随机性体现在每颗树的训练样本是随机的,树中每个节点的分裂属性集合也是随机选择确定的。有了这 2 个随机的保证,随机森林就不会产生过拟合的现象了。随机森林是用一种随机的方式建立的一个森林,森林是由很多棵决策树组成的,每棵树所分配的训练样本是随机的,树中每个节点的分裂属性集合也是随机选择确定的。
SVM
相关的 notebook 除了 cs231n 也可以看这里。
凸集、凸函数、凸优化
面试见得比较少,感兴趣的可以看下:
为什么深度学习中的图像分割要先编码后解码
降采样是手段不是目的:
降低显存和计算量,图小了显存也小,计算量也小;
增大感受野,使用同样 3x3 的卷积能在更大的图像范围上进行特征提取。大感受野对分割很重要,小感受野做不了多分类分割,而且分割出来很粗糙
多出几条不同程度额下采样分支,可以方便进行多尺度特征的融合。多级语义融合会让分类更加准确。
降采样的理论意义,我简单朗读一下,它可以增加对输入图像的一些小扰动的鲁棒性,比如图像平移,旋转等,减少过拟合的风险,降低运算量,和增加感受野的大小。相关链接:为什么深度学习中的图像分割要先编码再解码?
(全局)平均池化 average pooling 和 (全局) 最大池化 max pooling 的区别
最大池化保留了纹理特征
平均池化保留整体的数据特征
全局平均池化有定位的作用 (看知乎)
最大池化提取边缘等 “最重要” 的特征,而平均池化提取的特征更加 smoothly。对于图像数据,你可以看到差异。虽然两者都是出于同样的原因使用,但我认为 max pooling 更适合提取极端功能。平均池有时不能提取好的特征,因为它将全部计入并计算出平均值,这对于对象检测类型任务可能不好用但使用平均池化
的一个动机是每个空间位置具有用于期望特征
的检测器,并且通过平均每个空间位置,其行为类似于平均输入图像的不同平移的预测 (有点像数据增加)。Resnet 不是采用传统的完全连通层进行 CNN 分类,而是直接从最后一个 mlp 转换层输出特征图的空间平均值,作为通过全局平均合并层的类别置信度,然后将得到的矢量输入到 softmax 层。相比之下,Global average 更有意义且可解释,因为它强制实现了 feature 和类别之间的对应关系,这可以通过使用网络的更强大的本地建模来实现。此外,完全连接的层易于过拟合并且严重依赖于 dropout 正则化,而全局平均池化本身就是起到了正则化作用,其本身防止整体结构的过拟合。
全连接的作用,与 1x1 卷积层的关系
在实际使用中,全连接层可由卷积操作实现:对前层是全连接的全连接层可以转化为卷积核为 1x1 的卷积;而前层是卷积层的全连接层可以转化为卷积核为 hxw 的全局卷积,h 和 w 分别为前层卷积结果的高和宽使用 global average pooling 全局平均池化来代替卷积
全连接层(fully connected layers,FC)在整个卷积神经网络中起到 “分类器” 的作用。如果说卷积层、池化层和激活函数层等操作是将原始数据映射到隐层特征空间的话,全连接层则起到将学到的 “分布式特征表示” 映射到样本标记空间的作用。在实际使用中,全连接层可由卷积操作实现:对前层是全连接的全连接层可以转化为卷积核为 1x1 的卷积;而前层是卷积层的全连接层可以转化为卷积核为 hxw 的全局卷积,h 和 w 分别为前层卷积结果的高和宽
那么,1*1 卷积的主要作用有以下几点:
降维( dimension reductionality )。比如,一张 500x500 且厚度 depth 为 100 的图片在 20 个 filter 上做
1*1的卷积,那么结果的大小为500*500*20
。加入非线性。卷积层之后经过激励层,1*1 的卷积在前一层的学习表示上添加了非线性激励( non-linear activation ),提升网络的表达能力,但是也可以这样说:使之由单纯的线性变换,变为复杂的 feature map 之间的线性组合,从而实现特征的高度抽象过程。这一过程视为由线性变换为非线性,提高抽象程度。而非加入激活函数的作用。
个人应该是降维或者升维来减小参数个数和增加网络深度,以及跨通道的特征聚合
可以代替全连接层
concat 与 add(sum) 的区别
对于两路输入来说,如果是通道数相同且后面带卷积的话,add 等价于 concat 之后对应通道共享同一个卷积核。下面具体用式子解释一下。由于每个输出通道的卷积核是独立的,我们可以只看单个通道的输出。假设两路输入的通道分别为 X1, X2, ..., Xc 和 Y1, Y2, ..., Yc。那么 concat 的单个输出通道为(* 表示卷积):
而 add 的单个输出通道为:
concat 改成 sum 确实会好很多,这两个都是特征融合,到底有什么本质区别呢?我用的时候也没什么原则就是两个都试一下(其实更喜欢用 sum,毕竟更省显存)。
我之前做过类似 ASP 的实验,金字塔型空洞卷积融合,最后实验结果 sum 比 concat 要好一些,但是原因不知道怎么解释
我看过一些论文是 concat 比 sum 好的,可能这跟数据集等具体情况有关吧
不同的特征 sum 了,有什么意义呢,这些特征又损失了吧;如果直接 concat,让后面的网络学习,应该更好啊,用到的特征更多了
SSD 怎么改动变成 FasterRCNN
SSD 是直接分类,而 FasterRcnn 是先判断是否为背景再进行分类。一个是直接细分类,一个是先粗分类再细分类。
反向传播的原理
反向传播原理看 CS231n 中的 BP 过程,以及 Jacobian 的传播。
GD、SGD、mini batch GD 的区别
在百面深度学习中有相应的章节。
偏差、方差
有一篇文章比较好的介绍了,还有在那本电子版 CNNbook 中也有。
泛化误差可以分解成偏差的平方 + 方差 + 噪声
偏差度量了学习算法的期望预测和真实结果的偏离程度,刻画了学习算法本身的拟合能力
方差度量了同样大小的训练集的变动所导致的学习性能的变化,刻画了数据 扰动所造成的干扰
噪声表达了当前任务上学习任何算法所能达到的期望泛化误差下界,刻画了问题本身的难度。
偏差和方差一般称为 bias 和 variance,一般训练误差越强,偏差越小,方差越大,泛化误差在中间会有一个最小值。
如果偏差较大,方差较小,此时为欠拟合,而偏差较小,方差较大为过拟合。
为什么会梯度爆炸,如何防止
多层神经网络通常存在像悬崖一样的结构,这是由于几个较大的权重相乘导致的。遇到斜率很大的悬崖结构,梯度更新会很大程序地改变参数值,通常会完全跳过这类悬崖的结构。花书 P177.
分布式训练,多卡训练
精确率和召回率以及 PR 曲线
这个讲的比较好 (TP 与 FP 和 ROC 曲线):
Yolov2 相比 Yolov1 因为采用了先验框 (Anchor Boxes),模型的召回率大幅提升,同时 map 轻微下降了 0.2。
空洞卷积
空洞卷积一般都伴有 padding,如果 dilation=6,那么 padding 也等于 6。通过空洞卷积后的卷积特征图的大小不变,但是这个卷积的感受野比普通同等大小的卷积大。不过通道数是可以改变的。
在 DeepLabv3 + 中,最后的 ASPP 层,通过一个 1x1 卷积和 3 个 3x3 的空洞卷积,再 concat 上一个经过全局平均池化后双线性采样到同等维度的特征图。
数据不好怎么办,数据不均衡怎么处理、只有少量带标签怎么处理
具体问题具体分析。
训练过程中需要过拟合情况怎么办
深度学习 - 通用模型调试技巧
如何根据训练 / 验证损失曲线诊断我们的 CNN
关于训练神经网路的诸多技巧 Tricks(完全总结版)
深度学习中数据集很小是一种什么样的体验
如果模型的实际容量比较大,那么可以说模型可以完全学习到整个数据集,会发生过拟合。这时候再添加新的数据进去,模型的性能会进一步提升,说明模型还没有被撑死。期望风险是模型关于联合分布的期望损失,经验风险是模型关于训练数据集的平均损失。根据大树定律,当样本容量 N 趋于无穷时,经验风险趋于期望风险。但是当样本的容量比较小的的时候,经验风险最小化学习的效果未必就会很好,会产生 “过拟合” 的现象。结构风险最小化是为了防止过拟合而提出的策略。
正则化
在 Pytorch 中只能在 optim 中设置 weight_decay,目前只支持 L2 正则,而且这个正则是针对模型中所有的参数,不论是 w 还是 b,也包括 BN 中的 W 和 b。
BN 层和 L2 正则化一起有什么后果
就是因为 batch norm 过后, weight 影响没那么重了,所以 l2 weight decay 的效果就不明显了。证明了 L2 正则化与归一化相结合时没有正则化效应。相反,正则化会影响权重的范围,从而影响有效学习率。
ROIPooling 和 ROIAlign 的区别
空间金字塔池化 (SSP) 可以使不同尺寸的图像产生固定的输出维度。借题也问个问题,为什么 fast rcnn 的 roi pooling 是一个 max pooling 呢?roi pooling 后面也是做单个 roi 的 classification,为啥不和 classification 的 pooling 不同?我直觉是看 feature map 中的一个 channel,提取全局特征 (如,做 classification) 用 average pooling,提取提取全局信息;提取局部特征 (如,roi pooling) 应该用 max pooling,提取局部最明显的特征,成为 7×7 的 grid 后交给后面的 fc 来做 classification。相关介绍:
SPPNet - 引入空间金字塔池化改进 RCNN
自己实现图像增强算法
图像分类的 tricks
消融实验(Ablation experiment)
因为作者提出了一种方案,同时改变了多个条件 / 参数,他在接下去的消融实验中,会一一控制一个条件 / 参数不变,来看看结果,到底是哪个条件 / 参数对结果的影响更大。下面这段话摘自知乎,@人民艺术家:你朋友说你今天的样子很帅,你想知道发型、上衣和裤子分别起了多大的作用,于是你换了几个发型,你朋友说还是挺帅的,你又换了件上衣,你朋友说不帅了,看来这件衣服还挺重要的。
手撸 NMS 与 soft-NMS
逻辑回归和线性回归
线性回归:通过均方误差来寻找最优的参数,然后通过最小二乘法来或者梯度下降法估计:
线性回归和逻辑回归都是广义线性回归模型的特例
线性回归只能用于回归问题,逻辑回归用于分类问题(可由二分类推广至多分类)
线性回归无联系函数或不起作用,逻辑回归的联系函数是对数几率函数,属于 Sigmoid 函数
线性回归使用最小二乘法作为参数估计方法,逻辑回归使用极大似然法作为参数估计方法
两者都可以使用梯度下降法
注意:
来源文章:
什么是 attention,有哪几种
深度学习的线性和非线性
卷积是线性的
激活函数是非线性的
梯度消失和梯度爆炸的问题
Batch-norm 层的作用
Batch size 过小会使 Loss 曲线振荡的比较大,大小一般按照 2 的次幂规律选择,至于为什么?没有答出来,面试官后面解释是为了硬件计算效率考虑的,海哥后来也说 GPU 训练的时候开的线程是 2 的次幂个神经网络的本质是学习数据的分布,如果训练数据与测试数据的分布不同则会大大降低网络的泛化能力。随着网络训练的进行,每个隐层的变化使得后一层的输入发生变化,从而每一批训练的数据的分布也会变化,致使网络在每次迭代过程中都需要拟合不同的数据分布,增加数据训练的复杂度和过拟合的风险。
对数据的剧烈变化有抵抗能力。
BN 与贝叶斯的关系:
从 Bayesian 角度浅析 Batch Normalization
BN 跨卡训练怎么保证相同的 mean 和 var
在实践中,我发现,跨卡同步的 BN 对于 performance 相当有用。尤其是对于 detection,segmentation 任务,本来 Batch size 较小。如果 Batch Norm 能跨卡同步的话,就相当于增大了 Batch Norm 的 batch size 这样能估计更加准确的 mean 和 variance,所以这个操作能提升 performance。
如何实现 SyncBN
跨卡同步 BN 的关键是在前向运算的时候拿到全局的均值和方差,在后向运算时候得到相应的全局梯度。最简单的实现方法是先同步求均值,再发回各卡然后同步求方差,但是这样就同步了两次。实际上只需要同步一次就可以,我们使用了一个非常简单的技巧,改变方差的公式 (公式是图片,具体大家自己网上搜一下 SyncBN)。这样在前向运算的时候,我们只需要在各卡上算出与,再跨卡求出全局的和即可得到正确的均值和方差, 同理我们在后向运算的时候只需同步一次,求出相应的梯度与。我们在最近的论文 Context Encoding for Semantic Segmentation 里面也分享了这种同步一次的方法。有了跨卡 BN 我们就不用担心模型过大用多卡影响收敛效果了,因为不管用多少张卡只要全局的批量大小一样,都会得到相同的效果。
ResNet 为什么好用
出现因素:
随着网络的加深,优化函数越来越陷入局部最优解
随着网络层数的增加,梯度消失的问题更加严重,因为梯度在反向传播的时候会逐渐衰减
原因,误差传播公式可以写成参数 W 和导数 F 连乘的形式,当误差由第 L 层传播到输入以外的第一个隐含层的时候,会涉及到很多很多的参数和导数的连乘,这时误差很容易产生消失或者膨胀,导致不容易学习,拟合能力和泛化能力较差。残差层中的 F 层只需要拟合输入 x 与目标输出 H 的残差 H-x 即可,如果某一层的输出已经较好地拟合了期望结果,那么多一层也不回使得模型变得更差,因为该层的输出直接被短接到两层之后,相当于直接学习了一个恒等映射,而跳过的两层只需要拟合上层输出和目标之间的残差即可。
Resnet 的缺点
resnet 其实无法真正的实现梯度消失,这里面有很强的先验假设,并且 resnet 真正起作用的层只在中间,深层作用比较小 (到了深层就是恒等映射了),feature 存在利用不足的现象,add 的方式阻碍了梯度和信息的流通。
L1 范数和 L2 范数 应用场景
网络初始化有哪些方式,他们的公式初始化过程
目前的权重初始化分为三类:
全置为 0 - 几乎不会使用
随机初始化 (均匀随机、正态分布)
Xavier 作者 Glorot 认为,优秀的初始化应该使得各层的激活值和状态梯度的方差在传播过程中保持一致。适合 sigmoid,但是不适合 Relu。
He 初始化适用于 Relu。
初始化,说白了就是构建一个平滑的局部几何空间从而使得优化更简单 xavier 分布解析:
假设使用的是 sigmoid 函数。当权重值 (值指的是绝对值) 过小,输入值每经过网络层,方差都会减少,每一层的加权和很小,在 sigmoid 函数 0 附件的区域相当于线性函数,失去了 DNN 的非线性性。当权重的值过大,输入值经过每一层后方差会迅速上升,每层的输出值将会很大,此时每层的梯度将会趋近于 0. xavier 初始化可以使得输入值 x 方差经过网络层后的输出值 y 方差不变。
在 pytorch 中默认的权重初始化方式是何凯明的那个,举个例子:
resnet 中权重的初始化
求解模型参数量
卷积计算量
差不多这几个懂了就 OK。
普通卷积
可分离卷积
全连接
点卷积
可以看老潘的这篇文章:
多标签和多分类
那么,如何用 softmax 和 sigmoid 来做多类分类和多标签分类呢?
1、如何用 softmax 做多分类和多标签分类 现假设,神经网络模型最后的输出是这样一个向量 logits=[1,2,3,4], 就是神经网络最终的全连接的输出。这里假设总共有 4 个分类。用 softmax 做多分类的方法: tf.argmax(tf.softmax(logits))
首先用 softmax 将 logits 转换成一个概率分布,然后取概率值最大的作为样本的分类, 这样看似乎,tf.argmax(logits) 同样可以取得最大的值,也能得到正确的样本分类,这样的话 softmax 似乎作用不大. 那么 softmax 的主要作用其实是在计算交叉熵上,首先样本集中 y 是一个 one-hot 向量,如果直接将模型输出 logits 和 y 来计算交叉熵,因为 logits=[1,2,3,4],计算出来的交叉熵肯定很大,这种计算方式不对,而应该将 logits 转换成一个概率分布后再来计算,就是用 tf.softmax(logits) 和 y 来计算交叉熵,当然我们也可以直接用 tensorflow 提供的方法 sofmax_cross_entropy_with_logits 来计算 这个方法传入的参数可以直接是 logits,因为这个根据方法的名字可以看到,方法内部会将参数用 softmax 进行处理, 现在我们取的概率分布中最大的作为最终的分类结果,这是多分类。我们也可以取概率的 top 几个,作为最终的多个标签,或者设置一个阈值,并取大于概率阈值的。这就用 softmax 实现了多标签分类。
2、如何用 sigmoid 做多标签分类 sigmoid 一般不用来做多类分类,而是用来做二分类的,它是将一个标量数字转换到 [0,1] 之间,如果大于一个概率阈值(一般是 0.5),则认为属于某个类别,否则不属于某个类别。那么如何用 sigmoid 来做多标签分类呢?其实就是针对 logits 中每个分类计算的结果分别作用一个 sigmoid 分类器,分别判定样本是否属于某个类别。同样假设,神经网络模型最后的输出是这样一个向量 logits=[1,2,3,4], 就是神经网络最终的全连接的输出。这里假设总共有 4 个分类。tf.sigmoid(logits)
sigmoid 应该会将 logits 中每个数字都变成 [0,1] 之间的概率值,假设结果为[0.01, 0.05, 0.4, 0.6], 然后设置一个概率阈值,比如 0.3,如果概率值大于 0.3,则判定类别符合,那这里,样本会被判定为类别 3 和类别 4 都符合。
数据的输入为什么要归一化
为了消除数据特征之间的量纲影响在实际应用中,通过梯度下降法求解的模型通常是需要数据归一化的,包括线性回归、逻辑回归、支持向量机、神经网络等,但是决策模型不是很适用。
为什么说朴素贝叶斯是高偏差低方差?
首先,假设你知道训练集和测试集的关系。简单来讲是我们要在训练集上学习一个模型,然后拿到测试集去用,效果好不好要根据测试集的错误率来衡量。但很多时候,我们只能假设测试集和训练集的是符合同一个数据分布的,但却拿不到真正的测试数据。这时候怎么在只看到训练错误率的情况下,去衡量测试错误率呢?
由于训练样本很少(至少不足够多),所以通过训练集得到的模型,总不是真正正确的。(就算在训练集上正确率 100%,也不能说明它刻画了真实的数据分布,要知道刻画真实的数据分布才是我们的目的,而不是只刻画训练集的有限的数据点)。而且,实际中,训练样本往往还有一定的噪音误差,所以如果太追求在训练集上的完美而采用一个很复杂的模型,会使得模型把训练集里面的误差都当成了真实的数据分布特征,从而得到错误的数据分布估计。这样的话,到了真正的测试集上就错的一塌糊涂了(这种现象叫过拟合)。但是也不能用太简单的模型,否则在数据分布比较复杂的时候,模型就不足以刻画数据分布了(体现为连在训练集上的错误率都很高,这种现象较欠拟合)。过拟合表明采用的模型比真实的数据分布更复杂,而欠拟合表示采用的模型比真实的数据分布要简单。
在统计学习框架下,大家刻画模型复杂度的时候,有这么个观点,认为 Error = Bias + Variance。这里的 Error 大概可以理解为模型的预测错误率,是有两部分组成的,一部分是由于模型太简单而带来的估计不准确的部分(Bias),另一部分是由于模型太复杂而带来的更大的变化空间和不确定性(Variance)。
所以,这样就容易分析朴素贝叶斯了。它简单的假设了各个数据之间是无关的,是一个被严重简化了的模型。所以,对于这样一个简单模型,大部分场合都会 Bias 部分大于 Variance 部分,也就是说高偏差而低方差。
在实际中,为了让 Error 尽量小,我们在选择模型的时候需要平衡 Bias 和 Variance 所占的比例,也就是平衡 over-fitting 和 under-fitting。
Canny 边缘检测,边界检测算法有哪些
传统的目标检测
传统的目标检测一般分为以下几个步骤:
区域选择: 一幅图像通过 selective search 的方法,首先对原图进行分割 (聚类),然后通过计算相邻区域的相似度,最终找到 2000 个框,同样要与 GT 进行正例和负例的判断。
特征提取: 通过 SIFT 或者其他的特征提取方法,将 2000 个转化为特征向量
分类器分类: 将特征向量放入 SVM 中进行分类训练,同时将父类也放入分类器中进行训练。
经典的结构:
HoG + SVM
传统方法的缺点:
基于滑窗的区域选择策略没有针对性,时间复杂度高,窗口冗余
手工设计的特征对环境多样性的变化并没有很好的鲁棒性
腐蚀膨胀、开运算闭运算
可以看学习 OpenCV 第三版中的相关内容,搜索 erode、dilation
一些滤波器
图像中的高频、低频信息以及高通滤波器、低通滤波器
在图像中,边缘信息等比较明显的变化比较剧烈的像素点就是图像中的高频信息。而除了边缘部分,比较平缓的像素点变化不是很剧烈的内容信息就是低频信息。
高通滤波器就是突出变化剧烈 (边缘),去除低频部分,也就是当做边缘提取器。而低通滤波器主要是平滑该像素的亮度。主要用于去噪和模糊化,高斯模糊是最常用的模糊滤波器(平滑滤波器) 之一,它是一个削弱高频信号强度的低通滤波器。
Resize 双线性插值
在网络结构进行特征融合的时候,双线性插值的方式比转置卷积要好一点。因为转置卷积有一个比较大的问题就是如果参数配置不当,很容易出现输出 feature map 中带有明显棋盘状的现象。
需要注意的,最近邻插值的效果是最不好的。
双线性插值也分为两类:
align_corners=True
align_corners=False
一般来说,使用 align_corners=True 可以保证边缘对齐,而使用 align_corners=False 则会导致边缘突出的情况。这个讲的非常好:
代码实现的讲解:
gradient clipping 梯度裁剪
为了避免梯度爆炸而做出的改进,注意要和提前终止区别开来。(提前终止是一种正则化方法,因为当训练有足够能力表示甚至会过拟合的大模型时,训练误差会随着时间的推移逐渐降低但验证集的误差会再次上升。这意味着只要我们返回使验证集误差最低的参数设置即可) 第一种做法很容易理解,就是先设定一个 gradient 的范围如 (-1, 1), 小于 -1 的 gradient 设为 -1, 大于这个 1 的 gradient 设为 1.
实现一个简单的卷积
实现卷积一般用的是 im2col 的形式,但是面试中我们简单实现一个滑窗法就行了。比如:用 3x3 的卷积核 (滤波盒) 实现卷积操作。NCNN 中在 PC 端卷积的源码也是这样的。
参考:
卷积的过程
转置卷积的计算过程
1*1
的卷积核有什么用,3*3
的卷积核和一个1*3
加一个3*1
的有什么区别
1*1
的卷积核有什么用,3*3
的卷积核和一个1*3
加一个3*1
的有什么区别1x1 卷积可以改变上一层网络的通道数目。卷积核大于 1x1,意味着提特征需要邻域信息。
若提取横向纹理,则横向邻域信息密度比纵向信息密度高。
核扁横着最科学。若提纵向纹理,同理,瘦高竖着最好。
若你想提取的纹理种类丰富,那横向邻域信息密度的期望~= 纵向信息密度期望
所以对懒人来说,最优核的尺寸的期望是正方形。至于1*n
和n*1
,它们一般是搭配使用的,从而实现 nn 卷积核的感受野,可以在减少参数的同时增加层数,在 CNN 的较高层中使用可以带来一定的优势。卷积核并非都是正方形的,还可以是矩形,比如 35,在文本检测和车牌检测当中就有应用,这种设计主要针对文本行或者车牌的形状,能更好的学习特征。其实我觉得方形矩形影响不大,网络的学习能力是非常强的。当然我们也可以学习卷积的形状,类似于deformable convolution
,老潘后续会讲下。
ResNet 中 bottlenet 与 mobilenetv2 的 inverted 结构对比
注意,resnet 中是先降维再升维,而 mobilenetv2 中是先升维后降维 (所以称之为 inversed)。
卷积特征图大小的计算
很简单但是也很容易错的问题:
动态图和静态图的区别
静态图是建立一次,然后不断复用;静态图可以在磁盘中序列化,可以保存整个网络的结构,可以重载,在部署中很实用,在 tensorflow 静态图中条件和循环需要特定的语法,pytorch 只用 python 的语法就可以实现
而动态图是每次使用的时候建立,不容易优化,需要重复之前的代码,但是动态图比静态图代码更简洁
依据采用动态计算或是静态计算的不同,可以将这些众多的深度学习框架划分成两大阵营,当然也有些框架同时具有动态计算和静态计算两种机制(比如 MxNet 和最新的 TensorFlow)。动态计算意味着程序将按照我们编写命令的顺序进行执行。这种机制将使得调试更加容易,并且也使得我们将大脑中的想法转化为实际代码变得更加容易。而静态计算则意味着程序在编译执行时将先生成神经网络的结构,然后再执行相应操作。从理论上讲,静态计算这样的机制允许编译器进行更大程度的优化,但是这也意味着你所期望的程序与编译器实际执行之间存在着更多的代沟。这也意味着,代码中的错误将更加难以发现(比如,如果计算图的结构出现问题,你可能只有在代码执行到相应操作的时候才能发现它)。尽管理论上而言,静态计算图比动态计算图具有更好的性能,但是在实践中我们经常发现并不是这样的。
历年来所有的网络
这个可以看 CS231n 中的第九课以及
正式总结下:
LeNet-5: 第一个卷积,用来识别手写数组,使用的卷积大小为 5x5,s=1,就是普通的卷积核池化层结合起来,最后加上全连接层。
AlexNet: 在第一个卷积中使用了 11x11 卷积,第一次使用 Relu,使用了 NormLayer 但不是我们经常说的 BN。使用了 dropout,在两个 GPU 上进行了训练,使用的训练方式是模型并行、
ZFNet:AlexNet 的加强版,将 11x11 卷积改成了 7x7,也在 AlexNet 的基础上将卷积的通道深度加深。所以在分类比赛中比之前的效果好了些。
VGGNet: 只使用了小卷积 3x3(s=1) 以及常规的池化层,不过深度比上一个深了一些,最后几层也都是全连接层接一个 softmax。为什么使用 3x3 卷积,是因为三个 3x3 卷积的有效感受野和 7x7 的感受野一致,而且更深、更加非线性,而且卷积层的参数也更加地少,所以速度更快也可以适当加深层数。
DenseNet 不能简单说 densenet 更好,二者比较,ResNet 是更一般的模型,DenseNet 是更特化的模型。DenseNet 用于图像处理可能比 ResNet 表现更好,本质是 DenseNet 更能和图像的信息分布特点匹配,是使用了多尺度的 Kernel。但是也有缺点最直接的计算就是一次推断中所产生的所有 feature map 数目。有些框架会有优化,自动把比较靠前的层的 feature map 释放掉,所以显存就会减少,或者 inplace 操作通过重新计算的方法减少一部分显存,但是 densenet 因为需要重复利用比较靠前的 feature map,所以无法释放,导致显存占用过大。正是这种concat造成 densenet 能更密集的连接。
Wide Residual Networks
Densely Connected Convolutional Networks: 有利于减轻梯度消失的情况,增强了特征的流动。
一些统计知识
关于如何训练 (训练过程中的一些问题)
全连接层的好伴侣:空间金字塔池化(SPP)
感受野计算
感受野计算有两个公式,一个普通公式一个通项公式:
需要注意,卷积和池化都可以增加感受野。
参考资料
Last updated
Was this helpful?