深度学习面试知识点(八股文)总结
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
转子https://zhuanlan.zhihu.com/p/560482252
- 优化器
1.1 SGD
批梯度下降Batch gradient descent遍历全部数据集算一次损失函数计算量开销大计算速度慢不支持在线学习。随机梯度下降Stochastic gradient descentSGD: 每看一个数据就算一下损失函数然后求梯度更新参数。这个方法速度比较快但是收敛性能不太好。批量随机梯度下降Min-batch SGD用一些小样本来近似全部的其本质就是既然1个样本的近似不一定准那就用更大的30个或50个样本来近似。将样本分成m个mini-batch每个mini-batch包含n个样本。
我个人理解批量随机梯度下降其实更接近现在的Pytorch实际使用SGD优化器
深度学习中的batch与mini-batch
使用动量(Momentum)的随机梯度下降法(SGD): 在随机梯度的学习算法中每一步的步幅都是固定的而在动量学习算法中每一步走多远不仅依赖于本次的梯度的大小还取决于过去的速度。速度v是累积各轮训练参的梯度。
动量主要解决SGD的两个问题一是随机梯度的方法引入的噪声二是Hessian矩阵病态问题可以理解为SGD在收敛过程中和正确梯度相比来回摆动比较大的问题。
1.2 Adam算法
RMSprop将学习率分解成一个平方梯度的指数衰减的平均。 Adam中动量直接并入了梯度一阶矩指数加权的估计。其次相比于缺少修正因子导致二阶矩估计可能在训练初期具有很高偏置的RMSPropAdam还包括偏置修正修正从原点初始化的一阶矩动量项和非中心的二阶矩估计。
本质上是带有动量项的RMSprop它利用梯度的一阶矩估计和二阶矩估计动态调整每个参数的学习率。Adam的优点主要在于经过偏置校正后每一次迭代学习率都有个确定范围使得参数比较平稳
1.3 Adam与SGD的区别
SGD缺点是其更新方向完全依赖于当前batch计算出的梯度因而十分不稳定。
Adam的优点主要在于
考虑历史步中的梯度更新信息能够降低梯度更新噪声。
此外经过偏差校正后每一次迭代学习率都有个确定范围使得参数比较平稳。
但是Adam也有其自身问题可能会对前期出现的特征过拟合后期才出现的特征很难纠正前期的拟合效果。二者似乎都没法很好避免局部最优问题。
- 过拟合
一般定义模型在训练集上的表现很好但在测试集和新数据上的表现很差。
出现的原因
模型复杂度过高参数过多
训练数据比较小
训练集和测试集分布不一致
样本里面的噪声数据干扰过大导致模型过分记住了噪声特征。
解决的方法
降低模型复杂度
数据增强
正则化
L1 惩罚权重绝对值, 生成简单、可解释的模型
L2 惩罚权重平方和, 能够学习复杂数据模式
dropout
早停
过拟合(overfitting)和欠拟合(underfitting)比较
欠拟合在训练集和测试集上的性能都较差而过拟合往往能较好地学习训练集数据的性质而在测试集上的性能较差。在神经网络训练的过程中欠拟合主要表现为输出结果的高偏差 Bias模型不能适配训练样本有一个很大的偏差。而过拟合主要表现为输出结果的高方差 Variance 模型很好的适配训练样本但在测试集上表现很糟有一个很大的方差。
方差的含义方差度量了同样大小的训练集的变动所导致的学习性能的变化即刻画了数据扰动所造成的影响。
偏差的含义偏差度量了学习算法的期望预测与真实结果的偏离程度即刻画了学习算法本身的拟合能力。
- BN-LN等归一化层
3.1 BN层
BN计算公式如下
训练与推理时BN中的均值、方差计算差异
训练时均值、方差分别是该批次内数据相应维度的均值与方差推理时均值、方差是基于所有批次的期望计算所得。其中在推理时所用的均值和方差是通过移动平均计算得到的可以减少存储每个batch均值方差的内存。
具体的均值方差计算可视化图参考。
BN层的作用
加快网络的训练与收敛的速度; 控制梯度爆炸防止梯度消失。
3.2 LN层
LN层的计算
LN层与BN相比只考虑单个sample内的统计变量因此也不用使用BN实现中的running mean, running var.LN也完全不用考虑输入batch_size的问题。
至于为什么transformer中不使用BN归一化
解释一CV和NLP数据特性的不同对于NLP数据前向和反向传播中batch统计量及其梯度都不太稳定一个Batch中每个句子对应位置的分量不一定有意义。
解释二要能在某个维度做独立同分布假设才能合理归一化。对于CV来说batch之间的图像是独立的可以使用BN而对于自然语言的token相互是具有较强的关联性不是相互独立的。
transformer 为什么使用 layer normalization而不是其他的归一化方法
- 网络参数初始化
网络参数是否可以初始化为同一常数比如1
不可以在神经网络中如果将权值初始化为 0 或者其他统一的常量会导致后面的激活单元具有相同的值所有的单元相同意味着它们都在计算同一特征网络变得跟只有一个隐含层节点一样这使得神经网络失去了学习不同特征的能力
对于逻辑回归来说把参数初始化为0是可以的。
5. 网络感受野的计算
表示第
层的感受野
表示第
层卷积核的大小则第
层卷积输出特征的感受野为
特别地对于第1层即输入而言感受野大小为1。
除了上述式子外还可以从后往前推导如下
最后一层的感受野为该层卷积核大小依次往前推导 stride为步长Ksize为卷积核大小。
- 卷积输出特征图大小计算
参考
给定参数输入图片大小w, w, 卷积核大小 k, k, 步长 s, padding值 p, 输出特征图大小为
- 二维卷积实现
参考
import numpy as np
img = np.random.rand(2, 5, 5, 3) # bs x h x w x c
ker = np.ones([3, 3, 3, 6]) # h x w x c_in x c_out
def conv(img, ker, stride=1, padding=0):
size = list(img.shape)
pad_img = np.zeros([size[0], size[1] + 2 * padding, size[2] + 2 * padding, size[3]])
pad_img[:, padding:-padding, padding:-padding, :] = img
img = pad_img
# 套用卷积特征输出大小计算公式
out_size = (img.shape[1] + 2* padding - ker.shape[0]) // stride + 1
res = np.zeros([img.shape[0], out_size, out_size, ker.shape[3]])
# 假设batchsize等于1 则忽略此循环
for i in range(img.shape[0]):
# 卷积后的输出的通道数
for out_c in range(ker.shape[3]):
# hi表示padding后原图的坐标 每一次都是移动stride大小
for hi in range(0, out_size * stride, stride):
for wi in range(0, out_size * stride, stride):
# 确定要计算conv的区域
region = img[i, hi:hi + ker.shape[0], wi:wi + ker.shape[0], :]
# 卷积计算
res[i, hi // stride, wi // stride, out_c] = np.sum(region * ker[:, :, :, out_c])
return res
8. IoU与NMS python实现
IoU
import numpy as np
pred_box = np.rand(10, 4)
gt_box = np.rand(10, 4)
def get_IoU(pred_box, gt_box):
x_min = max(pred_box[0], gt_box[0])
y_min = max(pred_box[1], gt_box[1])
x_max = min(pred_box[2], gt_box[2])
y_max = min(pred_box[3], gt_box[3])
w = np.maximum(xmax-xmin+1, 0)
h = np.maximum(ymax-ymin+1, 0)
inter = w * h
union = (pred_box[2]-pred_box[0] + 1.0) * (pred_bbox[3] - pred_bbox[1] + 1.) + (gt_bbox[2] - gt_bbox[0] + 1.) * (gt_bbox[3] - gt_bbox[1] + 1.) - inter
IoU = inetr / union
return IoU
NMS 实现原理
首先对于每个类别将其中分类置信度小于阈值的框置信度设置为0
之后对所有box按照得分进行排序选出最高分对应的box_1;
遍历其余的box,如果和上面选择的box_1重叠面积IoU大于一定阈值则筛掉该box;
对剩余box继续选择一个最高分的box_2重复上面步骤直到剩余的box集合为空。
- 特殊形式卷积
可变形卷积
深度可分离卷积
一些轻量级的网络如mobilenet中会有深度可分离卷积depthwise separable convolution由depthwise(DW)和pointwise(PW)两个部分结合起来用来提取特征feature map其中前者卷积核每次只计算单张feature map卷积核大小为 k x k x 1后者是卷积只计算单个空间位置上的点卷积核大小为 1x1 x c_in.
转置卷积/反卷积
- Transformer自注意力
python 代码实现
self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)
def forward(self, x):
B, N, C = x.shape
# qkv: 3 x B x heads_num x N x c // heads_num
qkv = self.qkv(x).reshape(B, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)
# q, k, v : B x heads_num x N x c // heads_num
q, k, v = qkv[0], qkv[1], qkv[2] # make torchscript happy (cannot use tensor as tuple)
# attn : B x heads_num x N x N
attn = (q @ k.transpose(-2, -1)) * self.scale
attn = attn.softmax(dim=-1)
weights = attn
attn = self.attn_drop(attn)
x = (attn @ v).transpose(1, 2).reshape(B, N, C)
x = self.proj(x)
x = self.proj_drop(x)
return x, weights
- 梯度消失和爆炸
梯度消失的原因主要是是网络层较深其次是采用了不合适的损失函数会使得靠近输入层的参数更新缓慢。导致在训练时只等价于后面几层的浅层网络的学习。
梯度爆炸的原因一般出现在深层网络和权值初始化值太大的情况下。在深层神经网络或循环神经网络中误差的梯度可在更新中累积相乘。如果网络层之间的梯度值大于 1.0那么重复相乘会导致梯度呈指数级增长梯度变的非常大然后导致网络权重的大幅更新并因此使网络变得不稳定。
梯度爆炸会使得在训练过程中权重的值变得非常大以至于溢出导致模型损失变成 NaN等等。
解决方法梯度剪切对梯度设定阈值权重正则化batch normalization残差网络的捷径shortcut
- Pytorch 中的乘法
数乘运算 torch.mul
向量点积 torch.dot 计算两个张量的点乘积内积两个张量都为一维向量。
矩阵乘运算 torch.mm 输入的两个tensor shape分别是 n x c, c xm, 输出是 n x m;
torch.matmul对二维张量执行操作就是torch.mm, 此外还可以用于高维张量运算。
@符号乘法相当于矩阵乘torch.mm, 严格按照第一个参数的列数要等于第二个参数的行数。
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |