
WeThinkIn
2023/01/28阅读:20主题:橙心
【三年面试五年模拟】算法工程师的独孤九剑秘籍(前十二式汇总篇)V1版

Rocky Ding
公众号:WeThinkIn

写在前面
【三年面试五年模拟】栏目专注于分享AI行业中实习/校招/社招维度的必备面积知识点与面试方法,并向着更实战,更真实,更从容的方向不断优化迭代。也欢迎大家提出宝贵的意见或优化ideas,一起交流学习💪
大家好,我是Rocky。
本文是“三年面试五年模拟”之独孤九剑秘籍的特别系列,Rocky将独孤九剑秘籍前十二式的内容进行汇总梳理成汇总篇,并制作成pdf版本,大家可在公众号后台 【精华干货】菜单或者回复关键词“三年面试五年模拟” 进行取用。
由于篇幅的原因,本文只展现“三年面试五年模拟”独孤九剑秘籍第六式到第十二式的汇总内容。
除此之外Rocky还将YOLOv1-v7全系列大解析也制作成相应的pdf版本,大家可在公众号后台 【精华干货】菜单或者回复关键词“YOLO” 进行取用。
由于【三年面试五年模拟】系列都是Rocky在工作之余进行整理总结,难免有疏漏与错误之处,欢迎大家对可优化的部分进行指正,我将在后续的优化迭代版本中及时更正。
在【人人都是算法工程师】算法工程师的“三年面试五年模拟”之独孤九剑秘籍(先行版)中我们阐述了这个program的愿景与规划。本系列接下来的每一篇文章都将以独孤九剑秘籍框架的逻辑展开,考虑到易读性与文章篇幅,一篇文章中只选取每个分支技能树中的2-3个经典&高价值知识点和面试问题,并配以相应的参考答案(精简版),供大家参考。
希望独孤九剑秘籍的每一式都能让江湖中的英雄豪杰获益。

So,enjoy(与本文的BGM一起食用更佳哦):
正文开始
----【目录先行】----
深度学习基础:
-
什么是转置卷积的棋盘效应?
-
Instance Normalization的作用?
-
什么是有效感受野?
-
全局池化的作用?
-
深度学习中有哪些经典的优化器?
-
有哪些提高GAN训练稳定性的Tricks?
-
深度学习炼丹可以调节的一些超参数?
-
滑动平均的相关概念
-
Spectral Normalization的相关知识
-
激活函数的作用,常用的激活函数有哪些?
-
反向传播算法(BP)的概念及简单推导
-
分组卷积的相关知识
经典模型&&热门模型:
-
Focal Loss的作用?
-
YOLO系列的面试问题
-
有哪些经典的轻量型人脸检测模型?
-
LFFD人脸检测模型的结构和特点?
-
U-Net模型的结构和特点?
-
RepVGG模型的结构和特点?
-
GAN的核心思想?
-
面试常问的经典GAN模型?
-
FPN(Feature Pyramid Network)的相关知识
-
SPP(Spatial Pyramid Pooling)的相关知识
-
目标检测中AP,AP50,AP75,mAP等指标的含义
-
YOLOv2中的anchor如何生成?
机器学习基础:
-
机器学习有哪些种类?
-
L1正则为什么比L2正则更容易产生稀疏解?
-
格拉姆矩阵的相关概念?
-
感知损失的相关概念?
-
Accuracy、Precision、Recall、F1 Scores的相关概念?
-
梯度爆炸和梯度消失产生的原因及解决方法?
-
数据EDA逻辑(Exploratory Data Analysis)?
-
K折交叉验证逻辑?
-
KL散度相关概念
-
JS散度相关概念
-
K-means算法逻辑?
-
K近邻算法逻辑?
Python/C/C++知识:
-
Python中assert的作用?
-
Python中互换变量有不用创建临时变量的方法吗?
-
Python中的主要数据结构都有哪些?
-
Python中的可变对象和不可变对象?
-
Python中的None代表什么?
-
Python中 和 的区别?
-
Python中Numpy的broadcasting机制?
-
Python中的实例方法、静态方法和类方法三者区别?
-
Python中常见的切片操作
-
Python中如何进行异常处理?
-
Python中remove,del以及pop之间的区别?
-
C/C++中内存泄漏以及解决方法?
-
C/C++中野指针的概念?
-
C/C++中面向对象和面向过程的区别?
-
C/C++中常用容器功能汇总
-
C/C++中指针和引用的区别
-
C/C++中宏定义的相关知识
-
C/C++中typedef关键字的相关知识
模型部署:
-
什么是异构计算?
-
端侧部署时整个解决方案的核心指标?
-
什么是模型量化?
-
什么是模型剪枝?
-
主流AI端侧硬件平台有哪些?
-
主流AI端侧硬件平台一般包含哪些模块?
-
算法工程师该如何看待硬件侧知识?
-
现有的一些移动端开源框架?
-
端侧静态多Batch和动态多Batch的区别?
-
优化模型端侧性能的一些方法
-
ONNX的相关知识
-
TensorRT的相关知识
图像处理基础:
-
有哪些常用的图像质量评价指标?
-
什么是图像畸变?
-
RGB图像转为灰度图的方法?
-
仿射变换和透视变换的概念?
-
图像噪声的种类?
-
Python中OpenCV和PIL的区别?
-
有哪些常用的图像去噪算法?
-
有哪些常用的图像频域信息分离方法?
-
有哪些常用一阶微分梯度算子?
-
拉普拉斯算子的相关概念
-
OpenCV读取图像的格式?
-
中值滤波与均值滤波的相关概念
计算机基础:
-
Linux中的进程状态种类
-
Linux中ps aux指令与grep指令配合管理进程
-
Git,GitLab,SVN的相关知识
-
协程的相关概念
-
Linux系统的相关概念
-
Linux系统和Windows系统的区别?
-
POC验证测试的概念
-
Docker的相关概念及常用命令
-
深度学习中常用的文件格式汇总
-
TCP和UDP的区别?
开放性问题:
-
不同性质的公司如何使用好AI技术?
-
新时期的AI Lab该如何搭建?
-
业务侧,竞赛侧,研究侧成果如何互相转化?
-
深度学习的优势和局限?
-
如何保持数据持续稳定的支持业务?
-
如何分辨demo业务,一次性业务以及外包业务?
-
你觉得有哪些方法能增强公司的AI影响力?
-
你觉得面对一个业务场景,如何针对性设计算法解决方案?
-
对AI安全相关技术的发展前景的看法?
-
对GAN算法技术的发展前景的看法?
-
对一个零基础的CV算法学习者,有什么入门建议?
-
对CV算法技术的发展前景的看法?
----【深度学习基础】----
【一】什么是转置卷积的棋盘效应?

造成棋盘效应的原因是转置卷积的不均匀重叠(uneven overlap)。这种重叠会造成图像中某个部位的颜色比其他部位更深。
在下图展示了棋盘效应的形成过程,深色部分代表了不均匀重叠:

接下来我们将卷积步长改为2,可以看到输出图像上的所有像素从输入图像中接收到同样多的信息,它们都从输入图像中接收到一个像素的信息,这样就不存在转置卷带来的重叠区域。

我们也可以直接进行插值Resize操作,然后再进行卷积操作来消除棋盘效应。这种方式在超分辨率重建场景中比较常见。例如使用双线性插值和近邻插值等方法来进行上采样。
【二】Instance Normalization的作用?
Instance Normalization(IN)和Batch Normalization(BN)一样,也是Normalization的一种方法,只是IN是作用于单张图片,而BN作用于一个Batch。
BN对Batch中的每一张图片的同一个通道一起进行Normalization操作,而IN是指单张图片的单个通道单独进行Normalization操作。如下图所示,其中C代表通道数,N代表图片数量(Batch)。

IN适用于生成模型中,比如图片风格迁移。因为图片生成的结果主要依赖于某个图像实例,所以对整个Batch进行Normalization操作并不适合图像风格化的任务,在风格迁移中使用IN不仅可以加速模型收敛,并且可以保持每个图像实例之间的独立性。
下面是IN的公式:

其中t代表图片的index,i代表的是feature map的index。
【三】什么是有效感受野?
感受野的相关知识在之前的文章【三年面试五年模拟】算法工程师的独孤九剑秘籍(前六式汇总篇)中介绍过。
我们接着再看看有效感受野(effective receptive field, ERF)的相关知识。
一般而言,feature map上有效感受野要小于实际感受野。其有效性,以中心点为基准,类似高斯分布向边缘递减。
总的来说,感受野主要描述feature map中的最大信息量,有效感受野则主要描述信息的有效性。
【四】全局池化的作用?
全局池化主要包括全局平均池化和全局最大池化。


接下来,Rocky以全局平均池化为例,讲述其如何在深度学习网络中发挥作用。
刚才已经讲过,全局平均池化就是对最后一层卷积的特征图,每个通道求整个特征图的均值。如下图所示:

一般网络的最后会再接几个全连接层,但全局池化后的feature map相当于一像素,所以最后的全连接其实就成了一个加权相加的操作。这种结构比起直接的全连接更加直观,参数量大大幅下降,并且泛化性能更好:

全局池化的作用:
-
代替全连接层,降低参数量。 -
减少过拟合,增加泛化能力。
【五】深度学习中有哪些经典的优化器?
SGD(随机梯度下降)
随机梯度下降的优化算法在科研和工业界是很常用的。
很多理论和工程问题都能转化成对目标函数进行最小化的数学问题。
举个例子:梯度下降(Gradient Descent)就好比一个人想从高山上奔跑到山谷最低点,用最快的方式奔向最低的位置。
SGD的公式:

动量(Momentum)公式:

基本的mini-batch SGD优化算法在深度学习取得很多不错的成绩。然而也存在一些问题需解决:
-
选择恰当的初始学习率很困难。 -
学习率调整策略受限于预先指定的调整规则。 -
相同的学习率被应用于各个参数。 -
高度非凸的误差函数的优化过程,如何避免陷入大量的局部次优解或鞍点。
AdaGrad(自适应梯度)
AdaGrad优化算法(Adaptive Gradient,自适应梯度),它能够对每个不同的参数调整不同的学习率,对频繁变化的参数以更小的步长进行更新,而稀疏的参数以更大的步长进行更新。
AdaGrad公式:


表示t时刻的 梯度。
表示t时刻参数 的梯度平方和。
与SGD的核心区别在于计算更新步长时,增加了分母:梯度平方累积和的平方根。此项能够累积各个参数 的历史梯度平方,频繁更新的梯度,则累积的分母逐渐偏大,那么更新的步长相对就会变小,而稀疏的梯度,则导致累积的分母项中对应值比较小,那么更新的步长则相对比较大。
AdaGrad能够自动为不同参数适应不同的学习率(平方根的分母项相当于对学习率α进进行了自动调整,然后再乘以本次梯度),大多数的框架实现采用默认学习率α=0.01即可完成比较好的收敛。
优势: 在数据分布稀疏的场景,能更好利用稀疏梯度的信息,比标准的SGD算法更有效地收敛。
缺点: 主要缺陷来自分母项的对梯度平方不断累积,随时间的增加,分母项越来越大,最终导致学习率收缩到太小无法进行有效更新。
RMSProp
RMSProp结合梯度平方的指数移动平均数来调节学习率的变化。能够在不稳定的目标函数情况下进行很好地收敛。
计算t时刻的梯度:

计算梯度平方的指数移动平均数(Exponential Moving Average), 是遗忘因子(或称为指数衰减率),依据经验,默认设置为0.9。

梯度更新的时候,与AdaGrad类似,只是更新的梯度平方的期望(指数移动均值),其中 ,避免除数为0。默认学习率 。

优势: 能够克服AdaGrad梯度急剧减小的问题,在很多应用中都展示出优秀的学习率自适应能力。尤其在不稳定(Non-Stationary)的目标函数下,比基本的SGD、Momentum、AdaGrad表现更良好。
Adam
Adam优化器结合了AdaGrad和RMSProp两种优化算法的优点。对梯度的一阶矩估计(First Moment Estimation,即梯度的均值)和二阶矩估计(Second Moment Estimation,即梯度的未中心化的方差)进行综合考虑,计算出更新步长。
Adam的优势:
-
实现简单,计算高效,对内存需求少。 -
参数的更新不受梯度的伸缩变换影响。 -
超参数具有很好的解释性,且通常无需调整或仅需很少的微调。 -
更新的步长能够被限制在大致的范围内(初始学习率)。 -
能自然地实现步长退火过程(自动调整学习率)。 -
很适合应用于大规模的数据及参数的场景。 -
适用于不稳定目标函数。 -
适用于梯度稀疏或梯度存在很大噪声的问题。
Adam的实现原理:

计算t时刻的梯度:

然后计算梯度的指数移动平均数, 初始化为0。
类似于Momentum算法,综合考虑之前累积的梯度动量。
系数为指数衰减率,控制动量和当前梯度的权重分配,通常取接近于1的值。默认为0.9。

接着,计算梯度平方的指数移动平均数, 初始化为0。
系数为指数衰减率,控制之前的梯度平方的影响情况。默认为0.999。
类似于RMSProp算法,对梯度平方进行加权均值。

由于 初始化为0,会导致 偏向于0,尤其在训练初期阶段。
所以,此处需要对梯度均值 进行偏差纠正,降低偏差对训练初期的影响。

同时 也要进行偏差纠正:

最后总的公式如下所示:

其中默认学习率 , 避免除数变为0。
从表达式中可以看出,对更新的步长计算,能够从梯度均值和梯度平方两个角度进行自适应地调节,而不是直接由当前梯度决定。
Adam的不足:
虽然Adam算法目前成为主流的优化算法,不过在很多领域里(如计算机视觉的图像识别、NLP中的机器翻译)的最佳成果仍然是使用带动量(Momentum)的SGD来获取到的。
【六】有哪些提高GAN训练稳定性的Tricks?
1.输入Normalize
-
将输入图片Normalize到 之间。 -
生成器最后一层的输出使用Tanh激活函数。
Normalize非常重要,没有处理过的图片是没办法收敛的。图片Normalize一种简单的方法是(images-127.5)/127.5,然后送到判别器去训练。同理生成的图片也要经过判别器,即生成器的输出也是-1到1之间,所以使用Tanh激活函数更加合适。
2.替换原始的GAN损失函数和标签反转
-
原始GAN损失函数会出现训练早期梯度消失和Mode collapse(模型崩溃)问题。可以使用Earth Mover distance(推土机距离)来优化。
-
实际工程中用反转标签来训练生成器更加方便,即把生成的图片当成real的标签来训练,把真实的图片当成fake来训练。
3.使用具有球形结构的随机噪声 作为输入
-
不要使用均匀分布进行采样

-
使用高斯分布进行采样
4.使用BatchNorm
-
一个mini-batch中必须只有real数据或者fake数据,不要把他们混在一起训练。 -
如果能用BatchNorm就用BatchNorm,如果不能用则用instance normalization。

5.避免使用ReLU,MaxPool等操作引入稀疏梯度
-
GAN的稳定性会因为引入稀疏梯度受到很大影响。 -
最好使用类LeakyReLU的激活函数。(D和G中都使用) -
对于下采样,最好使用:Average Pooling或者卷积+stride。 -
对于上采样,最好使用:PixelShuffle或者转置卷积+stride。
最好去掉整个Pooling逻辑,因为使用Pooling会损失信息,这对于GAN训练没有益处。
6.使用Soft和Noisy的标签
-
Soft Label,即使用 和 两个区间的随机值来代替正样本和负样本的Hard Label。 -
可以在训练时对标签加一些噪声,比如随机翻转部分样本的标签。
7.使用Adam优化器
-
Adam优化器对于GAN来说非常有用。 -
在生成器中使用Adam,在判别器中使用SGD。
8.追踪训练失败的信号
-
判别器的损失=0说明模型训练失败。 -
如果生成器的损失稳步下降,说明判别器没有起作用。
9.在输入端适当添加噪声
-
在判别器的输入中加入一些人工噪声。 -
在生成器的每层中都加入高斯噪声。
10.生成器和判别器差异化训练
-
多训练判别器,尤其是加了噪声的时候。
11.Two Timescale Update Rule (TTUR)
对判别器和生成器使用不同的学习速度。使用较低的学习率更新生成器,判别器使用较高的学习率进行更新。
12. Gradient Penalty (梯度惩罚)
使用梯度惩罚机制可以极大增强 GAN 的稳定性,尽可能减少mode collapse问题的产生。
13. Spectral Normalization(谱归一化)
Spectral normalization可以用在判别器的weight normalization技术,可以确保判别器是K-Lipschitz连续的。
14. 使用多个GAN结构
可以使用多个GAN/多生成器/多判别器结构来让GAN训练更稳定,提升整体效果,解决更难的问题。
【七】深度学习炼丹可以调节的一些超参数?
-
预处理(数据尺寸,数据Normalization) -
Batch-Size -
学习率 -
优化器 -
损失函数 -
激活函数 -
Epoch -
权重初始化 -
NAS网络架构搜索
【八】滑动平均的相关概念
滑动平均(exponential moving average),或者叫做指数加权平均(exponentially weighted moving avergae),可以用来估计变量的局部均值,使得变量的更新与一段时间内的历史取值有关。
变量 在 时刻记为 , 为变量 在 时刻训练后的取值,当不使用滑动平均模型时 ,在使用滑动平均模型后, 的更新公式如下:

上式中, 。 相当于没有使用滑动平均。
时刻变量 的滑动平均值大致等于过去 个时刻 值的平均。并使用bias correction将 除以 修正对均值的估计。
加入Bias correction后, 和 的更新公式如下:

当 越大, 越接近1,则公式(1)和(2)得到的结果( 和 )将越来越接近。
当 越大时,滑动平均得到的值越和 的历史值相关。如果 ,则大致等于过去10个 值的平均;如果 ,则大致等于过去100个 值的平均。
下图代表不同方式计算权重的结果:


如上图所示,滑动平均可以看作是变量的过去一段时间取值的均值,相比对变量直接赋值而言,滑动平均得到的值在图像上更加平缓光滑,抖动性更小,不会因为某种次的异常取值而使得滑动平均值波动很大。
滑动平均的优势: 占用内存少,不需要保存过去10个或者100个历史 值,就能够估计其均值。滑动平均虽然不如将历史值全保存下来计算均值准确,但后者占用更多内存,并且计算成本更高。
为什么滑动平均在测试过程中被使用?
滑动平均可以使模型在测试数据上更鲁棒(robust)。
采用随机梯度下降算法训练神经网络时,使用滑动平均在很多应用中都可以在一定程度上提高最终模型在测试数据上的表现。
训练中对神经网络的权重 使用滑动平均,之后在测试过程中使用滑动平均后的 作为测试时的权重,这样在测试数据上效果更好。因为滑动平均后的 的更新更加平滑,对于随机梯度下降而言,更平滑的更新说明不会偏离最优点很远。比如假设decay=0.999,一个更直观的理解,在最后的1000次训练过程中,模型早已经训练完成,正处于抖动阶段,而滑动平均相当于将最后的1000次抖动进行了平均,这样得到的权重会更加鲁棒。
【九】Spectral Normalization的相关知识
Spectral Normalization是一种wegiht Normalization技术,和weight-clipping以及gradient penalty一样,也是让模型满足1-Lipschitz条件的方式之一。
Lipschitz(利普希茨)条件限制了函数变化的剧烈程度,即函数的梯度,来确保统计的有界性。因此函数更加平滑,在神经网络的优化过程中,参数变化也会更稳定,不容易出现梯度爆炸。
Lipschitz条件的约束如下所示:
其中 代表一个常数,即利普希茨常数。若 ,则是1-Lipschitz。
在GAN领域,Spectral Normalization有很多应用。在WGAN中,只有满足1-Lipschitz约束时,W距离才能转换成较好求解的对偶问题,使得WGAN更加从容的训练。
如果想让矩阵A映射: 满足K-Lipschitz连续,K的最小值为 ( 是 的最大特征值),那么要想让矩阵A满足1-Lipschitz连续,只需要在A的所有元素上同时除以 (Spectral norm)。
Spectral Normalization实际上在做的事,是将每层的参数矩阵除以自身的最大奇异值,本质上是一个逐层SVD的过程,但是真的去做SVD就太耗时了,所以采用幂迭代的方法求解。过程如下图所示:

得到谱范数 后,每个参数矩阵上的参数皆除以它,以达到Normalization的目的。
【十】激活函数的作用,常用的激活函数有哪些?
激活函数的作用
激活函数可以引入非线性因素,提升网络的学习表达能力。
常用的激活函数
Sigmoid 激活函数
函数的定义为:
如下图所示,其值域为 。也就是说,输入的每个神经元、节点都会被缩放到一个介于 和 之间的值。
当 大于零时输出结果会趋近于 ,而当 小于零时,输出结果趋向于 ,由于函数的特性,经常被用作二分类的输出端激活函数。

Sigmoid的导数:
当 时, 。
Sigmoid的优点:
-
平滑 -
易于求导 -
可以作为概率,辅助解释模型的输出结果
Sigmoid的缺陷:
-
当输入数据很大或者很小时,函数的梯度几乎接近于0,这对神经网络在反向传播中的学习非常不利。 -
Sigmoid函数的均值不是0,这使得神经网络的训练过程中只会产生全正或全负的反馈。 -
导数值恒小于1,反向传播易导致梯度消失。

Tanh激活函数
Tanh函数的定义为:
如下图所示,值域为 。

Tanh的优势:
-
Tanh函数把数据压缩到-1到1的范围,解决了Sigmoid函数均值不为0的问题,所以在实践中通常Tanh函数比Sigmoid函数更容易收敛。在数学形式上其实Tanh只是对Sigmoid的一个缩放形式,公式为 ( 是Sigmoid的函数)。 -
平滑 -
易于求导
Tanh的导数:
当 时, 。
由Tanh和Sigmoid的导数也可以看出Tanh导数更陡,收敛速度比Sigmoid快。

Tanh的缺点:
导数值恒小于1,反向传播易导致梯度消失。
Relu激活函数
Relu激活函数的定义为:
如下图所示,值域为 。

ReLU的优势:
-
计算公式非常简单,不像上面介绍的两个激活函数那样涉及成本更高的指数运算,大量节约了计算时间。 -
在随机梯度下降中比Sigmoid和Tanh更加容易使得网络收敛。 -
ReLU进入负半区的时候,梯度为0,神经元此时会训练形成单侧抑制,产生稀疏性,能更好更快地提取稀疏特征。 -
Sigmoid和Tanh激活函数的导数在正负饱和区的梯度都会接近于0,这会造成梯度消失,而ReLU函数大于0部分都为常数保持梯度不衰减,不会产生梯度消失现象。
稀疏:在神经网络中,这意味着激活的矩阵含有许多0。这种稀疏性能让我们得到什么?这能提升时间和空间复杂度方面的效率,常数值所需空间更少,计算成本也更低。
ReLU的导数:
通常 时,给定其导数为 和 。

ReLU的不足:
-
训练中可能会导致出现某些神经元永远无法更新的情况。其中一种对ReLU函数的改进方式是LeakyReLU。 -
ReLU不能避免梯度爆炸问题。
LeakyReLU激活函数
LeakyReLU激活函数定义为:
如下图所示( ),值域为 。

LeakyReLU的优势:
该方法与ReLU不同的是在 小于0的时候取 ,其中 是一个非常小的斜率(比如0.01)。这样的改进可以使得当 小于0的时候也不会导致反向传播时的梯度消失现象。
LeakyReLU的不足:
-
无法避免梯度爆炸的问题。 -
神经网络不学习 值。 -
在求导的时候,两部分都是线性的。
SoftPlus激活函数
SoftPlus激活函数的定义为:
值域为 。
函数图像如下:

可以把SoftPlus看作是ReLU的平滑。
ELU激活函数
ELU激活函数解决了ReLU的一些问题,同时也保留了一些好的方面。这种激活函数要选取一个 值,其常见的取值是在0.1到0.3之间。
函数定义如下所示:
如果我们输入的 值大于 ,则结果与ReLU一样,即 值等于 值;但如果输入的 值小于 ,则我们会得到一个稍微小于 的值,所得到的 值取决于输入的 值,但还要兼顾参数 ——可以根据需要来调整这个参数。公式进一步引入了指数运算 ,因此ELU的计算成本比ReLU高。
下面给出了 值为0.2时的ELU函数图:

ELU的导数:

导数图如下所示:

ELU的优势:
-
能避免ReLU中一些神经元无法更新的情况。 -
能得到负值输出。
ELU的不足:
-
包含指数运算,计算时间长。 -
无法避免梯度爆炸问题。 -
神经网络无法学习 值。
【十一】反向传播算法(BP)的概念及简单推导
反向传播(Backpropagation,BP)算法是一种与最优化方法(如梯度下降法)结合使用的,用来训练人工神经网络的常见算法。BP算法对网络中所有权重计算损失函数的梯度,并将梯度反馈给最优化方法,用来更新权值以最小化损失函数。该算法会先按前向传播方式计算(并缓存)每个节点的输出值,然后再按反向传播遍历图的方式计算损失函数值相对于每个参数的偏导数。
接下来我们以全连接层,使用sigmoid激活函数,Softmax+MSE作为损失函数的神经网络为例,推导BP算法逻辑。由于篇幅限制,这里只进行简单推导,后续Rocky将专门写一篇PB算法完整推导流程,大家敬请期待。
首先,我们看看sigmoid激活函数的表达式及其导数:
可以看到sigmoid激活函数的导数最终可以表达为输出值的简单运算。
我们再看MSE损失函数的表达式及其导数:
其中 代表ground truth(gt)值, 代表网络输出值。
由于偏导数中单且仅当 时才会起作用,故进行了简化。
接下来我们看看全连接层输出的梯度:

我们用 ,则能再次简化:
最后,我们看看那PB算法中每一层的偏导数:

输出层:
倒数第二层:
倒数第三层:
像这样依次往回推导,再通过梯度下降算法迭代优化网络参数,即可走完PB算法逻辑。
【十二】分组卷积的相关知识
分组卷积(Group Convolution)最早出现在AlexNet网络中,分组卷积被用来切分网络,使其能在多个GPU上并行运行。

普通卷积进行运算的时候,如果输入feature map尺寸是 ,卷积核有N个,那么输出的feature map与卷积核的数量相同也是N个,每个卷积核的尺寸为 ,N个卷积核的总参数量为 。
分组卷积的主要对输入的feature map进行分组,然后每组分别进行卷积。如果输入feature map尺寸是 ,输出feature map的数量为 个,如果我们设定要分成G个group,则每组的输入feature map数量为 ,则每组的输出feature map数量为 ,每个卷积核的尺寸为 ,卷积核的总数仍为N个,每组的卷积核数量为 ,卷积核只与其同组的输入map进行卷积,卷积核的总参数量为 ,易得总的参数量减少为原来的 。
分组卷积的作用:
-
分组卷积可以减少参数量。 -
分组卷积可以看成是稀疏操作,有时可以在较少参数量的情况下获得更好的效果(相当于正则化操作)。 -
当分组数量等于输入feature map通道数量,输出feature map数量也等于输入feature map数量时,分组卷积就成了Depthwise卷积,可以使参数量进一步缩减。
----【经典模型&&热门模型】----
【一】Focal Loss的作用?
Focal Loss是解决了分类问题中类别不均衡、分类难度差异的一个损失函数,使得模型在训练过程中更加聚焦在困难样本上。
Focal Loss是从二分类问题出发,同样的思想可以迁移到多分类问题上。
我们知道二分类问题的标准loss是交叉熵:
对于二分类问题我们也几乎适用sigmoid激活函数
,所以上面的式子可以转化成:
这里有
。
Focal Loss论文中给出的式子如下:

其中 是真实标签, 是预测概率。
我们再定义

那么,上面的交叉熵的式子可以转换成:

有了上面的铺垫,最初Focal Loss论文中接着引入了均衡交叉熵函数:

针对类别不均衡问题,在Loss里加入一个控制权重,对于属于少数类别的样本,增大 即可。但这样有一个问题,它仅仅解决了正负样本之间的平衡问题,并没有区分易分/难分样本。
为什么上述公式只解决正负样本不均衡问题呢?
因为增加了一个系数 ,跟 的定义类似,当 的时候 ;当 的时候, , 的范围也是 。因此可以通过设定 的值(如果 这个类别的样本数比 这个类别的样本数少很多,那么 可以取 到 来增加 这个类的样本的权重)来控制正负样本对整体Loss的贡献。
Focal Loss
为了可以区分难/易样本,Focal Loss雏形就出现了:

用于平衡难易样本的比例不均, 起到了对 的放大作用。 减少易分样本的损失,使模型更关注于困难易错分的样本。例如当 时,模型对于某正样本预测置信度 为 ,这时 ,也就是FL值变得很小;而当模型对于某正样本预测置信度 为0.3时, ,此时它对Loss的贡献就变大了。当 时变成交叉熵损失。
为了应对正负样本不均衡的问题,在上面的式子中再加入平衡交叉熵的 因子,用来平衡正负样本的比例不均,最终得到Focal Loss:

Focal Loss论文中给出的实验最佳取值为 , 。

【二】YOLO系列的面试问题
Rocky之前总结了YOLOv1-v7全系列的解析文章,帮助大家应对可能出现的与YOLO相关的面试问题,大家可按需取用:
【Make YOLO Great Again】YOLOv1-v7全系列大解析(汇总篇)
【三】有哪些经典的轻量型人脸检测模型?
人脸检测相对于通用目标检测来说,算是一个子任务。比起通用目标检测任务动辄检测1000个类别,人脸检测任务主要聚焦于人脸的单类目标检测,使用通用目标检测模型太过奢侈,有点“杀鸡用牛刀”的感觉,并且大量的参数冗余,会影响部署侧的实用性,故针对人脸检测任务,学术界提出了很多轻量型的人脸检测模型,Rocky在这里给大家介绍一些比较有代表性的:
-
libfacedetection -
Ultra-Light-Fast-Generic-Face-Detector-1MB -
A-Light-and-Fast-Face-Detector-for-Edge-Devices -
CenterFace -
DBFace -
RetinaFace -
MTCNN
【四】LFFD人脸检测模型的结构和特点?
Rocky在实习/校招面试中被多次问到LFFD模型以及面试官想套取LFFD相关算法方案的情况,说明LFFD模型在工业界还是比较有价值的,下面Rocky就带着大家学习一下LFFD模型的知识:
LFFD(A-Light-and-Fast-Face-Detector-for-Edge-Devices)适用于人脸、行人、车辆等单目标检测任务,具有速度快,模型小,效果好的特点。LFFD是Anchor-free的方法,使用感受野替代Anchors,并在主干结构上抽取8路特征图对从小到大的人脸进行检测,检测模块分为类别二分类与边界框回归。
LFFD模型结构

我们可以看到,LFFD模型主要由四部分组成:tiny part、small part、medium part、large part。
模型中并没有采用BN层,因为BN层会减慢17%的推理速度。其主要采用尽可能快的下采样来保持100%的人脸覆盖。
LFFD主要特点:
-
结构简单直接,易于在主流AI端侧设备中进行部署。
-
检测小目标能力突出,在极高分辨率(比如8K或更大)画面,可以检测其间10个像素大小的目标;
LFFD损失函数
LFFD损失函数是由regression loss和classification loss的加权和。
分类损失使用了交叉熵损失。
回归损失使用了L2损失函数。
LFFD论文地址:LFFD: A Light and Fast Face Detector for Edge Devices论文地址
【五】U-Net模型的结构和特点?
U-Net网络结构如下所示:

U-Net网络的特点:
-
全卷积神经网络:使用 卷积完全取代了全连接层,使得模型的输入尺寸不受限制。 -
左半部分网络是收缩路径(contracting path):使用卷积和max pooling层,对feature map进行下采样。 -
右半部分网络是扩张路径(expansive path):使用转置卷积对feature map进行上采样,并将其与收缩路径对应层产生的特征图进行concat操作。上采样可以补充特征信息,加上与左半部分网络收缩路径的特征图进行concat(通过crop操作使得两个特征图尺寸一致),这就相当于在高分辨率和高维特征当中做一个融合折中。 -
U-Net提出了让人耳目一新的编码器-解码器整体结构,让U-Net充满了生命力与强适应性。
U-Net在医疗图像,缺陷检测以及交通场景中有非常丰富的应用,可以说图像分割实际场景,U-Net是当仁不让的通用Baseline。
U-Net的论文地址:U-Net
【六】RepVGG模型的结构和特点?
RepVGG模型的基本架构由20多层 卷积组成,分成5个stage,每个stage的第一层是stride=2的降采样,每个卷积层用ReLU作为激活函数。
RepVGG的主要特点:
-
卷积在GPU上的计算密度(理论运算量除以所用时间)可达1x1和5x5卷积的四倍. -
直筒型单路结构的计算效率比多路结构高。 -
直筒型单路结构比起多路结构内存占用少。 -
单路架构灵活性更好,容易进一步进行模型压缩等操作。 -
RepVGG中只含有一种算子,方便芯片厂商设计专用芯片来提高端侧AI效率。
那么是什么让RepVGG能在上述情形下达到SOTA效果呢?
答案就是结构重参数化(structural re-parameterization)。

在训练阶段,训练一个多分支模型,并将多分支模型等价转换为单路模型。在部署阶段,部署单路模型即可。这样就可以同时利用多分支模型训练时的优势(性能高)和单路模型推理时的好处(速度快、省内存)。
更多结构重参数化细节知识将在后续的篇章中展开介绍,大家尽情期待!
【七】GAN的核心思想?
2014年,Ian Goodfellow第一次提出了GAN的概念。Yann LeCun曾经说过:“生成对抗网络及其变种已经成为最近10年以来机器学习领域最为重要的思想之一”。GAN的提出让生成式模型重新站在了深度学习这个浪潮的璀璨舞台上,与判别式模型开始谈笑风生。
GAN由生成器 和判别器 组成。其中,生成器主要负责生成相应的样本数据,输入一般是由高斯分布随机采样得到的噪声 。而判别器的主要职责是区分生成器生成的样本与 样本,输入一般是 样本与相应的生成样本,我们想要的是对 样本输出的置信度越接近 越好,而对生成样本输出的置信度越接近 越好。与一般神经网络不同的是,GAN在训练时要同时训练生成器与判别器,所以其训练难度是比较大的。

在提出GAN的第一篇论文中,生成器被比喻为印假钞票的犯罪分子,判别器则被当作警察。犯罪分子努力让印出的假钞看起来逼真,警察则不断提升对于假钞的辨识能力。二者互相博弈,随着时间的进行,都会越来越强。在图像生成任务中也是如此,生成器不断生成尽可能逼真的假图像。判别器则判断图像是 图像,还是生成的图像。二者不断博弈优化,最终生成器生成的图像使得判别器完全无法判别真假。
GAN的对抗思想主要由其目标函数实现。具体公式如下所示:

上面这个公式看似复杂,其实不然。跳出细节来看,整个公式的核心逻辑其实就是一个min-max问题,深度学习数学应用的边界扩展到这里,GAN便开始发光了。
接着我们再切入细节。我们可以分两部分开看这个公式,即判别器最小化角度与生成器最大化角度。在判别器角度,我们希望最大化这个目标函数,因为在公示第一部分,其表示 样本 输入判别器后输出的置信度,当然是越接近 越好。而公式的第二部分表示生成器输出的生成样本 再输入判别器中进行进行二分类判别,其输出的置信度当然是越接近 越好,所以 越接近 越好。
在生成器角度,我们想要最小化判别器目标函数的最大值。判别器目标函数的最大值代表的是真实数据分布与生成数据分布的JS散度,JS散度可以度量分布的相似性,两个分布越接近,JS散度越小(JS散度是在初始GAN论文中被提出,实际应用中会发现有不足的地方,后来的论文陆续提出了很多的新损失函数来进行优化)
写到这里,大家应该就明白GAN的对抗思想了,下面是初始GAN论文中判别器与生成器损失函数的具体设置以及训练的具体流程:

在图中可以看出,将判别器损失函数离散化,其与交叉熵的形式一致,我们也可以说判别器的目标是最小化交叉熵损失。
【八】面试常问的经典GAN模型?
-
原始GAN及其训练逻辑 -
DCGAN -
CGAN -
WGAN -
LSGAN -
PixPix系列 -
CysleGAN -
SRGAN系列
【九】FPN(Feature Pyramid Network)的相关知识
FPN的创新点
-
设计特征金字塔的结构 -
提取多层特征(bottom-up,top-down) -
多层特征融合(lateral connection)
设计特征金字塔的结构,用于解决目标检测中的多尺度问题,在基本不增加原有模型计算量的情况下,大幅度提升小物体(small object)的检测性能。
原来很多目标检测算法都是只采用高层特征进行预测,高层的特征语义信息比较丰富,但是分辨率较低,目标位置比较粗略。假设在深层网络中,最后的高层特征图中一个像素可能对应着输出图像 的像素区域,那么小于 像素的小物体的特征大概率已经丢失。与此同时,低层的特征语义信息比较少,但是目标位置准确,这是对小目标检测有帮助的。FPN将高层特征与底层特征进行融合,从而同时利用低层特征的高分辨率和高层特征的丰富语义信息,并进行了多尺度特征的独立预测,对小物体的检测效果有明显的提升。

传统解决这个问题的思路包括:
-
图像金字塔(image pyramid),即多尺度训练和测试。但该方法计算量大,耗时较久。 -
特征分层,即每层分别输出对应的scale分辨率的检测结果,如SSD算法。但实际上不同深度对应不同层次的语义特征,浅层网络分辨率高,学到更多是细节特征,深层网络分辨率低,学到更多是语义特征,单单只有不同的特征是不够的。
FPN的主要模块
-
Bottom-up pathway(自底向上线路) -
Top-down path(自顶向下线路) -
Lareral connections(横向链路)

Bottom-up pathway(自底向上线路)
自底向上线路是卷积网络的前向传播过程。在前向传播过程中,feature map的大小可以在某些层发生改变。
Top-down path(自顶向下线路)和Lareral connections(横向链路)
自顶向下线路是上采样的过程,而横向链路是将自顶向下线路的结果和自底向上线路的结构进行融合。
上采样的feature map与相同大小的下采样的feature map进行逐像素相加融合(element-wise addition),其中自底向上的feature先要经过 卷积层,目的是为了减少通道维度。
FPN应用
论文中FPN直接在Faster R-CNN上进行改进,其backbone是ResNet101,FPN主要应用在Faster R-CNN中的RPN和Fast R-CNN两个模块中。
FPN+RPN:
将FPN和RPN结合起来,那RPN的输入就会变成多尺度的feature map,并且在RPN的输出侧接多个RPN head层用于满足对anchors的分类和回归。
FPN+Fast R-CNN:
Fast R-CNN的整体结构逻辑不变,在backbone部分引入FPN思想进行改造。
【十】SPP(Spatial Pyramid Pooling)的相关知识
在目标检测领域,很多检测算法最后使用了全连接层,导致输入尺寸固定。当遇到尺寸不匹配的图像输入时,就需要使用crop或者warp等操作进行图像尺寸和算法输入的匹配。这两种方式可能出现不同的问题:裁剪的区域可能没法包含物体的整体;变形操作造成目标无用的几何失真等。
而SPP的做法是在卷积层后增加一个SPP layer,将features map拉成固定长度的feature vector。然后将feature vector输入到全连接层中。以此来解决上述的尴尬问题。

SPP的优点:
-
SPP可以忽略输入尺寸并且产生固定长度的输出。 -
SPP使用多种尺度的滑动核,而不是只用一个尺寸的滑动窗口进行pooling。 -
SPP在不同尺寸feature map上提取特征,增大了提取特征的丰富度。

在YOLOv4中,对SPP进行了创新使用,Rocky已在【Make YOLO Great Again】YOLOv1-v7全系列大解析(Neck篇)中详细讲解,大家可按需取用~
【十一】目标检测中AP,AP50,AP75,mAP等指标的含义
AP:PR曲线下的面积。

AP50: 固定IoU为50%时的AP值。
AP75:固定IoU为75%时的AP值。
AP@[0.5:0.95]:把IoU的值从50%到95%每隔5%进行了一次划分,并对这10组AP值取平均。
mAP:对所有的类别进行AP的计算,然后取均值。
mAP@[.5:.95](即mAP@[.5,.95]):表示在不同IoU阈值(从0.5到0.95,步长0.05)(0.5、0.55、0.6、0.65、0.7、0.75、0.8、0.85、0.9、0.95)上的平均mAP。
【十二】YOLOv2中的anchor如何生成?
YOLOv2中引入K-means算法进行anchor的生成,可以自动找到更好的anchor宽高的值用于模型训练的初始化。
但如果使用经典K-means中的欧氏距离作为度量,意味着较大的Anchor会比较小的Anchor产生更大的误差,聚类结果可能会偏离。
由于目标检测中主要关心anchor与ground true box(gt box)的IOU,不关心两者的大小。因此,使用IOU作为度量更加合适,即提高IOU值。因此YOLOv2采用IOU值为评判标准:
具体anchor生成步骤与经典K-means大致相同,在下一个章节中会详细介绍。主要的不同是使用的度量是 ,并将anchor作为簇的中心。
----【机器学习基础】----
【一】机器学习有哪些种类?
机器学习中通常根据数据是否有标签可以分为监督学习(supervised learning)、非监督学习(unsupervised learning),半监督学习(semi-supervised learning)以及弱监督学习(weakly supervised learning)。
监督学习
机器学习模型在训练过程中的所有数据都有标签,就是监督学习的逻辑。
监督学习是最常见的学习种类,常见场景为分类和回归问题。
深度学习模型大都数都遵从监督学习的流程,并且支持向量机(Support Vector Machine, SVM),朴素贝叶斯(Naive Bayes),逻辑回归(Logistic Regression),K近邻(K-Nearest Neighborhood, KNN),决策树(Decision Tree),随机森林(Random Forest),AdaBoost以及线性判别分析(Linear Discriminant Analysis, LDA)等也属于监督学习算法的范畴。
非监督学习
非监督学习与监督学习完全相反,机器学习模型在训练过程中的所有数据都是没有标签的,主要学习数据本身的一些特性。
比如想象一个人从来没有见过猫和狗,如果给他看了大量的猫和狗,虽然他还是没有猫和狗的概念,但是他是能够观察出每个物种的共性和两个物种间的区别的,并对这个两种动物予以区分。
半监督学习
半监督学习的逻辑是机器学习模型在训练过程中,部分数据有标签,与此同时另外一部分数据没有标签,并把这两种数据都利用起来用于训练。
弱监督学习
弱监督学习的逻辑是机器学习模型在训练过程中使用的数据的标签存在不可靠的情况。这里的不可靠可以是标注不正确,多重标记,标记不充分,局部标记,包含噪声等情况。一个直观的例子是相对于分割的标签来说,分类的标签就是弱标签。
【二】L1正则为什么比L2正则更容易产生稀疏解?
我们首先可以设目标函数为 ,目标函数中的权值参数为 ,那么目标函数和权值参数的关系如下所示:

如上图所示,最优的 在绿色的点处,而且 非零。
我们首先可以使用L2正则进行优化,新的目标函数: ,示意图如下蓝线所示:

我们可以看到,最优的 出现在黄点处, 的绝对值减小了,更靠近横坐标轴,但是依然是非零的。
为什么是非零的呢?
我们可以对L2正则下的目标函数求导:

我们发现,权重 每次乘上的是小于1的倍数进行收敛,而且其导数在 时没有办法做到左右两边导数异号,所以L2正则使得整个训练过程稳定平滑,但是没有产生稀疏性。
接下来我们使用L1正则,新的目标函数: ,示意图如下粉线所示:

这里最优的 就变成了0。因为保证使用L1正则后 处左右两个导数异号,就能满足极小值点形成的条件。
我们来看看这次目标函数求导的式子:

可以看出L1正则的惩罚很大, 每次都是减去一个常数的线性收敛,所以L1比L2更容易收敛到比较小的值,而如果 ,就能保证 处取得极小值。
上面只是一个权值参数 。在深层网路中,L1会使得大量的 最优值变成0,从而使得整个模型有了稀疏性。
【三】格拉姆矩阵的相关概念?
n维欧式空间中任意k个向量之间两两的内积所组成的矩阵,称为这k个向量的格拉姆矩阵(Gram matrix),这是一个对称矩阵。


其中对角线元素提供了k个不同特征图(a1,a2 ... ,ak)各自的信息,其余元素提供了不同特征图之间的相关信息。既能体现出有哪些特征,又能体现出不同特征间的紧密程度。图像风格迁移领域将其定义为风格特征。
格拉姆矩阵在风格迁移中有广泛的应用,深度学习中经典的风格迁移流程是:
-
准备基线图像和风格图像。
-
使用特征提取器分别提取基线图像和风格图像的feature map。
-
分别计算两个图像的feature map的格拉姆矩阵,以两个图像的格拉姆矩阵的差异最小化为优化目标,不断调整基线图像,使风格不断接近目标风格图像。
【四】感知损失的相关概念?
感知损失在图像生成领域中比较常用。其核心是将gt图片卷积得到的高层feature与生成图片卷积得到的高层feature进行回归,从而约束生成图像的高层特征(内容和全局结构)。

上面的公式中,划线部分代表了高层特征,一般使用VGG作为特征提取器。
【五】Accuracy、Precision、Recall、F1 Scores的相关概念?
首先Rocky介绍一下相关名词:
-
TP(True Positive): 预测为正,实际为正 -
FP(False Positive): 预测为正,实际为负 -
TN(True Negative):预测为负,实际为负 -
FN(false negative): 预测为负,实际为正
Accuracy、Precision、Recall、F1 Scores的公式如下所示:

Accuracy(准确率):分类正确的样本数占样本总数的比例。
Precision(精准度/查准率):当前预测为正样本类别中被正确分类的样本比例。
Recall(召回率/查全率):预测出来的正样本占正样本总数的比例。
F1-score是Precision和Recall的综合。F1-score越高,说明分类模型越稳健。
【六】梯度爆炸和梯度消失产生的原因及解决方法?
梯度爆炸和梯度消失问题
一般在深层神经网络中,我们需要预防梯度爆炸和梯度消失的情况。
梯度消失(gradient vanishing problem)和梯度爆炸(gradient exploding problem)一般随着网络层数的增加会变得越来越明显。
例如下面所示的含有三个隐藏层的神经网络,梯度消失问题发生时,接近输出层的hiden layer3的权重更新比较正常,但是前面的hidden layer1的权重更新会变得很慢,导致前面的权重几乎不变,仍然接近初始化的权重,这相当于hidden layer1没有学到任何东西,此时深层网络只有后面的几层网络在学习,而且网络在实际上也等价变成了浅层网络。

产生梯度爆炸和梯度消失问题的原因
我们来看看看反向传播的过程:
(假设网络每一层只有一个神经元,并且对于每一层 )

可以推导出:

而sigmoid的导数 如下图所示:

可以知道, 的最大值是 ,而我们初始化的权重 通常都小于1,因此 ,而且链式求导层数非常多,不断相乘的话,最后的结果越来越小,趋向于0,就会出现梯度消失的情况。
梯度爆炸则相反,