机器学习面试题面经
深度学习卷积神经网络面试题面经
PyTorch面试题面经
Python面试题面经
Linux,Git面试题面经
HR面试题面经
本文内容参考魏秀参《解析卷积神经网络》
手写卷积池化代码
池化层的反向传播
cnn的反向传播
-
1卷积神经网络基本操作
-
2卷积神经网络的压缩
-
3数据扩充
-
4数据预处理
-
5网络参数初始化
-
6激活函数
-
7目标函数
-
8网络正则化
-
9超参数设定和网络训练
-
10不平衡样本的处理
-
11模型集成方法
提高泛化能力的方法:
增广,减小网络,加正则,dropout,bn
共享特征有助于减少神经网络中的参数数量,一定程度上减小了模型的计算复杂度
1.卷积神经网络基本操作
卷积操作的作用
卷积是一种局部操作,通过
一定大小的卷积核作用于局部图像区域获得图像的局部信息。比如边缘滤波等。
事实上,卷积网络中的卷积核参数是通过网络训练学出的,除了可以学到类似的横向,纵向边缘滤波器,还可以学到任意角度的边缘滤波器。不仅如此,检测性状,颜色,纹理等众多基本模式的滤波器都可以包含在一个足够复杂的深层卷积神经网络中。通过组合(池化激活等)这些滤波器以及随着网络的后序操作的进行,基本而一般的模式会逐渐被抽象为具有高层语义的概念表示,并以此对应到具体的样本类别。
池化的作用
池化层不包含可学习的参数。只需要指定赤化类型,池化操作核大小,池化步长等超参数。池化有平均池化,最大池化,随机池化(对输入数据中的元素按照一定概率大小随机选择,并不像最大池化那样总是选最大元素,对随机池化而言,元素值大的响应被选中的概率也大。可以说在全局意义上,随机池化与平均池化近似,在局部意义上,则服从最大池化的准则)
作用:其实就是降采样操作,池化层的引入是仿照人的视觉系统对视觉输入对象进行降维(降采样)和抽象。研究者认为池化有三种作用:
-
特征不变性:池化操作让模型更关注是否存在某些特征而不是特征的具体位置。可看做是一种很强的闲言,使特征学习包含某种程度的自由度,能容忍一些特征微小的位移
-
特征降维:降采样,池化结果中一个元素对应于原输入数据的一个子区域,因此池化相当于在空间范围内做了维度约检,从而使模型可以抽取更广范围的特征。同时减小下一层输入的大小,进而减小计算量和参数个数
-
在一定程度上防止过拟合,方便优化
根据相关理论,
特征提取的误差主要来自两个方面:
-
邻域大小受限造成的估计值
方差增大
-
卷积层参数误差造成估计
均值的偏移
-
平均池化能减小第一种误差(邻域大小受限造成的估计值方差增大),
更多的保留图像的背景信息
-
最大池化能减小第二种误差(卷积层参数误差造成估计均值的偏移),
更多的保留纹理信息
-
随机池化介于两者之间,通过对像素点按照数值大小赋予概率,再按照概率进行采样,在平均意义上,与均值近似,在局部意义上,服从最大池化的准则。
平均池化与最大池化分别适用于什么场景:
-
当map中的信息都应该有所贡献的时候用avgpool,比如图像分割中常用global avgpool来获取全局上下文关系,比如224x224图像分类将最后的7x7map进行avgpool而不是maxpool。因为深层高级语义信息一般来说都能够帮助分类器分类。
-
反之
为了减少无用信息时候用maxpool,比如浅层网络常见到maxpool,因为刚开始几层对图像而言包含较多的无关信息,另外avgpool与maxpool输出值幅度波动大,可以加一些归一化操作。具体使用场景根据任务来,实际效果炼丹后才知道。
激活函数
引入激活函数的目的是为了增加整个网络的表达能力(即非线性)。否则若干现行操作层的堆叠仍然只能起到线性映射的作用,无法形成复杂的函数。
sigmoid
公式图像,适用范围,缺点
relu
公式图像,解决了什么问题
2.卷积神经网络的压缩
在追求模型高准确率的同时,尽可能的降低其复杂度,以达到性能与开销(时间计算量)上的平衡。给定一小部分参数子集便能够完整的重构出剩余的参数。这种冗余在训练阶段很必要,因为DL问题是一个极其复杂的非凸优化问题,对于现有的基于梯度下降的优化算法而言,这种参数冗余能保证网络能够收敛到一个比较好的最优值。因而一定程度上,网络越深,参数越多,模型越复杂,最终效果往往也越好。
模型压缩技术主要分为两个部分:前端压缩,后端压缩
当然也可以将前端压缩的输出作为后端压缩的输入,能够在最大程度上减少模型的复杂度。
低秩近似
CNN的实现通过矩阵相乘完成,通常权重矩阵往往稠密且巨大,从而带来巨大计算和存储开销。为解决这个问题直观想法是,若能将稠密矩阵由若干个小规模矩阵近似重构出来,那么便能够有效降低存储于计算开销。
低秩近似在
小网络模型上取得了不错的效果,但其参数量与网络层数呈线性变化趋势,随着层数增加与模型复杂度提高,其搜索空间急剧增大。
剪枝与稀疏约束
通过剪枝处理,在减小模型复杂度的同时,还能有效防止过拟合,提升模型泛化性。在训练中,需要一定冗余的参数数量来保证模型的可塑性与容量,在完成训练之后,则可以通过剪枝操作来移除这些荣誉参数,使得模型更加成熟。给定一个预训练好的网络模型,常用剪枝算法的流程:
-
衡量神经元重要程度(剪枝算法最重要的核心步骤)。根据剪枝粒度不同,神经元定义可以是一个权重连接,也可以是整个滤波器。
-
移除掉一部分不重要的神经元。可以根据阈值来判断神经元是否可以被剪除,也可以按照重要程度排序,剪除一定比例的神经元。后者简单
-
对网络进行微调。剪枝操作不可避免影响网络精度,为防止对分类性能造成过大破坏,需要对剪枝后的模型进行微调。
-
返回第1步,进行下一轮剪枝。
参数量化
量化是指从权重中归纳出若干“代表”,由这些代表来表示某一类权重的具体数值。代表被存储在码本中,而原权重矩阵只需记录各自代表的索引即可,从而极大降低存储开销。即使采用最简单的标量量化算法,也能在保持网络性能不受显著影响的情况下,将模型大小减少8-16倍。不足在于,当压缩率比较大时容易造成分类精度大幅度下降。
二值网络
所有参数取值只能是+1或-1。在普通NN中,一个参数由单精度浮点型表示,参数二值化能将存储开销降低为原来的1/32。二值化需要解决两个基本问题:
知识蒸馏
在不改变模型复杂度情况下,增加监督信息的丰富程度肯定会带来性能上的提升。知识蒸馏是迁移学习的一种,目的是将庞大复杂模型学到的知识通过一定 的手段迁移到精简的小模型上,使得小模型能够获得与大模型相近的性能。这两个模型分别扮演老师(大模型)和学生(小模型)角色:让学生自己学的话,收效甚微;若能经过一个老师的指导,便能够事半功倍,学生甚至有可能超越老师。
紧凑的网络结构
设计出很多更加紧凑的网络结构,将这些新结构运用到神经网络设计中来,能够使模型在规模与精度之间达到一个较好的平衡。比如:
3.数据扩充
数据扩充不仅能够增加样本数量,还能增加样本多样性。一方面避免过拟合,另一方面会带来模型性能的提升。
简单的数据扩充
-
水平翻转:使数据集扩充一倍
-
随机抠取(random crops):一般用0.8-0.9倍的正方形在原图的随机位置处抠取图像块,每张图像随机抠取的次数决定了数据集扩充的倍数。使用正方形是因为CNN网络输入是正方形,以正方形抠图避免了矩形抠取后序的图像拉伸操作带来的分辨率失真
-
尺度变换:将图像分辨率变为原图的0.8,0.9,1.1,1.2,1.3等倍数。将尺度变换后的图像作为扩充的训练样本加入训练
-
旋转:-30,-15,15,30度等
-
色彩抖动:对原图或已经变换的图进行操作。在RGB颜色空间对原有RGB色彩分布进行轻微扰动,也可以在HSV颜色空间尝试随机改变图像原有饱和度和透明度,或对色调进行微调
-
实际中,一般对上面方法叠加组合使用,将数据扩增多倍甚至数十倍
特殊的数据扩充方式
4.数据预处理
机器学习中,对特征进行归一化
实践中,对每个特征减去平均值来中心化数据非常重要,这种归一化处理方式被称为“中心式归一化”。CNN中预处理通常是计算训练集图像像素均值,之后再处理训练集、验证集和测试集图像时要减去该均值。减去均值的原理是:默认自然图像是一种平稳分布(每个维度的统计都服从相同的分布),此时在每个样本上减去平均值可以移除共同部分,凸显个体差异。注意均值只能通过训练集计算得到,然后再训练集验证集测试集中使用。否则违背ML基本原理:模型训练过程中只能从训练数据中获取信息。
5.网络参数初始化
WL = np.random.randn(WL.shape[0],WL.shape[1])* np.sqrt(1/n)
-
He等人将对此改进-将非线性映射造成的影响考虑进初始化中,将Xavier方法中方差规范化的分母应该是 sqrt(n/2),而不是 sqrt(n)
-
以上是服从高斯分布,均匀分布也是一种很好的初始化分布,当参数初始化服从均匀分布,由于分布性质不同,均匀分布需要制定其取值区间,则Xavier和He初始化方法分别修改为
-
其他初始化方法:比如利用预训练模型初始化,预训练模型已经在原先任务上收敛到理想的局部最优解,加上预训练模型容易获得,因此将其作为新任务的参数初始化无疑是一个优质首选
6.激活函数
常用的激活函数,sigmoid, tanh(x), ReLU, Leaky ReLU, 参数化ReLU, 随机化ReLU和指数化线性单元(ELU)
sigmoid
tanh(x)
以0为中心,但是仍然会出现梯度饱和现象
ReLU
函数在大于等于0范围内为1,否则为0.
但是缺点:对小于0的卷积结果响应,他们一旦变为负值将无法再影响网络响应
Leaky ReLU
为缓解ReLU中小于0部分的死区现象,将x<0部分调整为f(x) = a*x,其中a为0.01或者0.001数量级较小正数。a为超参数,需要人为设定,但是在实际中并不稳定
参数化ReLU
为解决Leaky ReLU中超参数a不容易设定的问题:直接将a也作为一个网络中可学习的变量融入模型的整体训练过程。
-
自动学习a的值,分类精度上优于原始ReLU
-
自由度较大的通道独享参数的参数化ReLU更优
随机化ReLU与ELU
7.目标函数
分类任务的目标函数
-
交叉熵损失函数:
-
当样本被正确分类且函数间隔大于1时,合页损失才是0,否则损失是1-y(wx+b)。这也就是说合页损失函数不仅要正确分类,而且确信度足够高时损失才是0.也就是说合页损失函数对学习有更高的要求。
-
坡道损失函数:非凸损失可以很好解决这个问题(分类中坡道,回归中Tukey's biweight),他们针对噪声数据和离群点具备良好的抗噪特性,因此是鲁棒损失函数。其共同特点是在分类(回归)误差较大的区域进行截断,使得较大误差不再大程度影响整个误差函数。公式如上图,s指定了截断的位置,坡道损失也就是在s处截断的合页损失,也称为截断合页损失。上图表示两种损失函数的对比。在断点处不可导,但不影响使用。s由分类类别数c决定,一般s=-1/(c-1)
为了进一步提高学习到的特征的判别性,研究者基于交叉熵损失函数设计了新型损失函数,比如大间隔交叉熵,中心损失函数。这些损失函数考虑了增加类间距离,减小类内差异等不同要素,进一步提升了网络学习特征的判别能力。
回归任务目标函数
其他任务目标函数
很多问题不能直接用分类和回归来衡量,比如年龄判断的30岁左右。这种可以用标记分布来描述,这种分布明显区别于分类问题的离散标记,也区别与回归问题的连续标记。与回归问题区别在于,回归问题虽然标记连续,缺不符合一个合法的概率分布。假设
为网络模型对于输入样本xi的最终输出结果,利用标记分布技术解决问题之前,先需要将h转化为一个合法分布。以softmax为例可将h转化为:
,其中
代表标记向量的第k维。针对预测的标记向量
,通常可用KL散度来度量其余真实标记向量y的误差,KL散度也称KL损失。下面两种写法等价,通过KL散度可以衡量样本标记分布于真实标记分布之间的差异,并利用该差异指导模型训练。
8.网络正则化
正则化是机器学习中通过显式的控制模型复杂度来避免模型过拟合、确保泛化性能的一种有效方式。在此介绍5种常用的CNN网络正则化方法。
-
L2正则化(权重衰减,岭回归):深度模型常用L2和L1正则对操作层(卷积层,分类层等)进行正则化,约束模型复杂度。假设待正则的网络层参数为w,L2正则项形式为:
,λ控制正则项大小,较大λ将较大程度约束模型复杂度。一般将正则项加入目标函数,通过整体目标函数的误差反向传播,从而达到正则项影响和指导网络训练的目的。
-
L1正则化:
,L1正则化除了同L2正则化一样能约束参数量级外,L1正则化还能起到使参数更稀疏的作用。稀疏化的结果使优化后的参数w一部分为0,另一部分为非0值。非0值那部分参数可起到选择重要参数或特征维度的作用,同时可起到去除噪声的效果。此外L2和L1正则可以联合使用
dropout代码
keep_prob = 0.8 # 设置神经元保留概率
d3 = np.random.rand(a3.shape[0], a3.shape[1]) < keep_prob
a3 = np.multiply(a3, d3)
a3 /= keep_prob
9.超参数设定和网络训练
介绍一些网络设计过程中超参数设定技巧和训练技巧,如学习率设定,批规范化操作和网络优化策略的选择等。
-
批规范化操作(batch normalization,BN):使得网络每层输入数据分布稳定,不仅加快了模型收敛速度,更重要是在一定程度上
缓解了深层网络的梯度消失,从而使训练深层网络模型更加稳定容易,也有一定正则效果。BN不仅适合于深层网络,也适合于浅层网络。算法流程:在模型每次随机梯度下降训练时,通过mini-batch来对相应的网络响应做规范化操作,使得结果(输出信号各个维度)的均值为0,方差为1. 算法共分为四步,前两步分别计算批处理的数据均值和方差,第三步则根据计算的均值方差对该批数据进行规范化。
最后尺度变化和偏移操作是为了让因训练所需而刻意加入的BN能够有可能还原最初的输入(
),
从而保证整个网络的容量。
-
-
BN为什么效果好:对NN的各层输出,由于经过了层内操作作用,其分布显然与各层对应的输入信号分布不同,而且差异会随着深度增大越来越大,不过label不变,因此就是内部协变量偏移。实验发现,可通过BN来规范化某些层或所有层的输入,从而可以固定每层输入信号的均值与方差。这样即使网络模型较深层的响应或梯度很小,也可通过BN的规范化作用将其尺度变大,以此解决深层网络训练可能带来的梯度消失问题。比如一组随机数很小,然后经过规范化后,原本微小差异被拉大,这样缓解了梯度消失现象。
-
作用:BN一般作用在非线性映射函数前。若网络训练收敛速率慢或梯度爆炸等无法训练也可尝试用BN解决。同时BN可以加快模型训练速度,甚至提高模型精度。
-
BN在训练时和测试时差别:BN就是为了让网络在每一层都保持相近的分布。
-
BN计算均值的时候计算多少次:假设[b,c,h,w],计算b*h*w次,因为是相当于对每个channel计算
-
BN共有多少个参数:2*c个参数
-
BN训练时为啥不用全量均值和方差:用全量均值和方差容易过拟合,对于BN,就是对每一批数据归一化到相同的分布,而每一批的数据均值和方差肯定是有差别的,而不是用固定值,这个差别能够增加模型鲁棒性,同时也一定程度上减少过拟合。正因如此,一般BN要求数据完全打乱,并用一个较大batch,否则,一个batch无法较好的代表训练集的分布,会影响模型的训练。若batch较小,可以使用GN(group normalization)
-
BN和dropout共同使用出现的问题:存在神经方差不一致行为。 Understanding the Disharmony between Dropout and Batch Normalization by Variance Shift。解决方法有两种:1.在BN后使用dropout,2.使用高斯dropout
https://www.jianshu.com/p/8013aa6d1f4c
BN:(batchnorm)是在batch上,对NHW做归一化,对小batchsize效果不好
LN:layernorm在通道方向上,对CHW做归一化,主要对RNN作用明显
IN:instancenorm在图像像素上,对HW做归一化,用在风格迁移上
GN:(groupnorm)将channel分组,然后再做归一化
switchableNorm将BN,LN,IN结合,赋予权重,让网络自己去学习归一化层应该使用什么方法。
BN算法过程:
-
沿着通道计算每个batch的均值u
-
沿着通道计算每个batch的方差σ^2
-
对x做归一化
-
加入缩放和平移变量γ和β,归一化后的值,y=γx+β。
加入缩放平移变量的原因是:不一定每次都是标准正太分布,也许需要偏移或者拉伸。保证每一次数据经过归一化后还保留原有学习来的特征,同时又能完成归一化操作,加速训练。这两个参数是用来学习的参数。
-
缺点:对batchsize的大小比较敏感,由于每次计算均值和方差是在一个batch上,所以如果batchsize太小,则计算的均值、方差不足以代表整个数据分布。
BN代码
BN代码
import numpy as np
def Batchnorm(x, gamma, beta, bn_param):
# x_shape:[B, C, H, W]
running_mean = bn_param['running_mean']
running_var = bn_param['running_var']
results = 0.
eps = 1e-5
x_mean = np.mean(x, axis=(0, 2, 3), keepdims=True)
x_var = np.var(x, axis=(0, 2, 3), keepdims=True0)
x_normalized = (x - x_mean) / np.sqrt(x_var + eps)
results = gamma * x_normalized + beta
# 因为在测试时是单个图片测试,这里保留训练时的均值和方差,用在后面测试时用
running_mean = momentum * running_mean + (1 - momentum) * x_mean
running_var = momentum * running_var + (1 - momentum) * x_var
bn_param['running_mean'] = running_mean
bn_param['running_var'] = running_var
return results, bn_param
LN:LN针对深度网络某一层的所有神经元的输入进行normalize操作。LN中同层神经元输入拥有相同的均值和方差,不同的输入样本有不同的均值和方差。LN用于RNN效果比较明显,但是在CNN上,不如BN。
def Layernorm(x, gamma, beta):
# x_shape:[B, C, H, W]
results = 0.
eps = 1e-5
x_mean = np.mean(x, axis=(1, 2, 3), keepdims=True)
x_var = np.var(x, axis=(1, 2, 3), keepdims=True0)
x_normalized = (x - x_mean) / np.sqrt(x_var + eps)
results = gamma * x_normalized + beta
return results
IN,instance normalization:在图像风格化中,生成结果主要依赖于某个图像实例,所以对整个batch归一化不适合图像风格化中,因而对HW做归一化。可以加速模型收敛,并且保持每个图像实例之间的独立。
def Instancenorm(x, gamma, beta):
# x_shape:[B, C, H, W]
results = 0.
eps = 1e-5
x_mean = np.mean(x, axis=(2, 3), keepdims=True)
x_var = np.var(x, axis=(2, 3), keepdims=True0)
x_normalized = (x - x_mean) / np.sqrt(x_var + eps)
results = gamma * x_normalized + beta
return results
GN,Group normalization:主要针对bn对小batchsize效果差,GN将channel方向分group,然后每个group内做归一化,算(C//G)HW的均值,这样与batchsize无关,不受其约束
def GroupNorm(x, gamma, beta, G=16):
# x_shape:[B, C, H, W]
results = 0.
eps = 1e-5
x = np.reshape(x, (x.shape[0], G, x.shape[1]/16, x.shape[2], x.shape[3]))
x_mean = np.mean(x, axis=(2, 3, 4), keepdims=True)
x_var = np.var(x, axis=(2, 3, 4), keepdims=True0)
x_normalized = (x - x_mean) / np.sqrt(x_var + eps)
results = gamma * x_normalized + beta
return results
10.不平衡样本的处理
不平衡的训练样本会导致训练模型侧重样本数目较多的类别,而轻视样本数目较少的类别,这样模型在测试数据上的泛华能力就会受到影响。在分类、回归、语义分割、图像深度估计等任务重经常出现。主要从数据层面和算法层面介绍不平衡样本问题的处理方法。
11.模型集成方法
-
数据层面的集成方法
-
测试阶段数据扩充:图像多尺度,随机抽取等。比如随机抽取,对某张测试图像可得到n张随机抽取图像,测试阶段只需要用训练好的网络对n张图片分别预测,将结果置信度平均作为该图片的结果。
-
简易集成法:对于样本较多的类采用降采样,每次采样数依照样本数目最少的类别而定,这样每类取到的样本数可保持均等。采样结束后,针对每次采样得到的子数据集训练模型,如此训练采样反复多次。最后对测试数据的预测依据训练得到的若干个模型的结果取平均或投票获得。这样,在模型集成的同时,还能够缓解数据不平衡带来的问题。
-
模型层面的集成方法
-
单模型集成
-
多层特征融合:深度CNN具有层次性的特点,不同层特征包含的语义特征可以互补。一般多层特征融合操作时可直接将不同层网络特征级联。对于特征融合应该选择哪些网络层,实践经验:最好使用靠近目标函数的几层卷积特征,因为越深层特征包含的高层语义性越强,分辨能力越强。低层特征较普适,用于特征融合可能起不到作用甚至会起到相反作用。
-
网络快照集成法:NN存在许多局部最优解,经典的minibatchSGD只能让网络模型收敛到其中一个局部最优解。快照法利用这些局部最优解对单个网络模型集成。通过循环调整网络学习率可使网络依次收敛到不同的局部最优解处。
-
多模型集成:
-
多模型生成策略:
-
同一模型不同初始化:特别对小样本学习场景,先对同一模型不同初始化,之后将得到的网络模型进行结果集成会缓解其随机性,提升最终结果的预测任务。
-
同一模型不同训练轮数:可降低随机误差,也避免了训练轮数过多带来的过拟合风险。
-
不同目标函数:交叉熵损失,合页损失,大间隔交叉熵损失,中心损失等作为目标函数训练模型。预测时可对不同模型置信度级别进行平均或者投票。也可以做特征级别模型集成:将不同网络得到的深度特征抽出级联后作为最终特征,最后离线训练浅层分类器完成预测任务。
-
不同网络结构:vgg,resnet等不同模型集成
-
多模型集成方法: