目录
神经网络视觉基础
基础知识
神经网络的基本原理

神经网络的训练,主要目的就是通过学习算法得到各层神经元之间的连接权重和偏置参数等,然后通过参数计算出输入值的输出。
卷积神经网络包括输入层、中间层、输出层。而中间层可以细化为卷积层、激活层、池化层和全连接层。
卷积层(局部感知、权值共享)–(图像特征提取)
卷积层中,卷积操作由一个或者多个卷积核(filter)在前层图像上选择相应的区域做卷积运算,然后按一定的步长作滑动运算,依次提取图像区域的像素级特征,图像特征综合后经过激活函数激活,完成一次输入到输出的特征提取过程,卷积后的特征图反映了前层图像的融合特征。
卷积操作

经卷积后的矩阵尺寸大小计算公式为(输入图片大小WxW,卷积核FxF,步长S,padding = P) $$ N = (W - F + 2P) / S + 1 $$
激活层 (通过函数把特征保留并映射到输出端)
卷积神经网络在卷积操作后作用非线性激活函数,可以实现对输入信息的非线性变化,从而使网络的输入和输出产生非线性映射关系,激活层对卷积后的逐元素作用激活函数,实现输入和输出信息的同维。引入激活函数的目的是为了增加神经网络的非线性拟合能力。
-
“为什么一定要非线性?”
因为神经网络的每一次输入和输出都是线性求和过程,下一层输出承接了上一层输入函数的线性变换,如果没有非线性激活函数,那么无论神经网络有多少层,最后的输出都是输入的线性组合。这样的线性组合并不能解决复杂的问题。
激活函数
- Sigmoid(又称“逻辑函数”)
$$ f(x) = \frac {1} {1 + e^{-x}} $$
$$ y = \begin{cases} 1, 当S(x) \ge 0.5 \\\ 0, 当S(x) < 0.5 \end{cases} $$
$$ S(x)’ = \frac{e^{-x}}{(1+e^{-x})^2} $$

优点:
- 值域为[0,1],他对每个神经元的输出进行了归一化,适合用于将预测概率作为输出的模型
- 梯度平滑,避免了跳跃式 的输出
缺点:
- 接近0或1的神经元梯度趋近于0,容易引起梯度消失,即无法反向传播更新权重。
- 计算量大,需要更高的算力
- ReLU(目前主流的激活函数)
$$ f(x) = Max(0, x) $$
$$ f’(x) = Sgn(x) $$
相比sigmoid函数,其计算速度快,收敛速度快(因为输入为负值时,神经元不会被激活,所以网络很稀疏,能更好的提取相关特征,拟合训练数据)。ReLU函数能够最大化发挥神经元的筛选能力。
-
不足:很容易训练过程中使部分kernel废掉,且无法再次被激活。
-
“ReLU是分段线性函数,它是怎么实现非线性的?”
ReLU在整个定义域内并不是线性的,组合多个(线性操作+ReLU)就可以任意划分空间,对于层数比较少的神经网络,用ReLU作为激活函数,那非线性肯定没有那么强,但是当层数多达几十甚至上千,虽然,单独的隐藏层是线性的,但是很多的隐藏层表现出来的就是非线性的。(即用很多小的直线可以拟合出曲线效果一样)。
- Leaky ReLU

- Softmax (所有输出概率和为1)
$$ o_i = \frac {e^{y_i}} {\sum_je^{y_j}} $$
- 用于多分类问题的激活函数
- 在零点不可微,负输入的梯度为零会产生“死亡神经元”
对于二分类问题,理论上使用sigmoid和softmax没有区别,因为数学表达式的形式是一样的。 对于多分类非互斥问题(多标签分类)如人和女人,使用sigmoid更合适。 对于多分类互斥问题(单标签分类),使用softmax更合适。
池化层(对特征图进行稀疏处理)
降低信息冗余,提升模型的尺度不变性、旋转不变性、防止过拟合。
MaxPooling(最大值池化)

全连接层(特征空间–>样本标记空间)
卷积层提取了各种特征,但很多物体可能拥有同一类特征,全连接层相当于组合了这些特征起到了分类器的功能。

损失函数
损失函数是用来衡量模型预测值$f(x)$与真实值$Y$的差异程度的运算函数,他是一个非负实数值函数,通常表示为$L(Y|f(x))$。
损失函数使用主要是在模型的训练阶段,每批训练数据送入模型后,通过前向传播输出预测值,然后损失函数会计算出预测值和真实值之间的差异值,也就是损失值。得到损失值之后,模型通过反向传播去更新各个参数,来降低真实值与预测值之间的损失,使模型越来越准确。
“反向传播过程” $$ \omega_{11} = \omega_{11} - \eta \frac{\partial \delta}{\partial \omega_{11}} $$ 通过链式求导法则和梯度下降,逐步修改权重参数$\omega$。其中 $\eta$ 为学习率,$\delta$为损失值。
基于距离度量的损失函数:
-
均方误差损失函数(MSE) $$ L(Y|f(x)) = \frac{1}{n} \sum_{i=1}^N(Y_i - f(x_i))^2 $$
-
L2损失函数(欧氏距离) $$ L(Y|f(x)) = \sqrt{\frac{1}{n} \sum_{i=1}^N (Y_i - f(x_i))^2} $$
-
L2损失函数(曼哈顿距离) $$ L(Y|f(x)) = \sum_{i=1}^N |Y_i - f(x_i)| $$
-
Smooth L1损失函数(主要用在目标检测中防止梯度爆炸) $$ L(Y|f(x)) = \begin{cases} \frac{1}{2}(Y-f(x))^2 \qquad \quad |Y-f(x)| < 1 \\\ |Y-f(x)|- \frac{1}{2} \qquad |Y-f(x)| \ge 1 \end{cases} $$
-
huber损失函数(平方损失+绝对损失) $$ L(Y|f(x)) = \begin{cases} \frac{1}{2}(Y-f(x))^2 \qquad \qquad |Y-f(x)| \le \delta \\\ \delta |Y-f(x)|- \frac{1}{2} \delta^2 \qquad |Y-f(x)| > \delta \end{cases} $$
基于概率分布度量的损失函数:(涉及概率分布或预测类别出现的概率的问题中应用广泛)
-
KL散度函数(相对熵) $$ L(Y|f(x)) = \sum_{i=1}^n Y_i \times log(\frac{Y_i}{f(x_i)}) $$
-
交叉熵损失 $$ L(Y|f(x)) = - \sum_{i=1}^n Y_i \times logf(x_i) $$ 交叉熵损失函数刻画了实际输出概率与期望输出概率之间的相似度,交叉熵的值越小,两个概率分布就越接近,特别是在正负样本不均衡的分类问题中,常用交叉熵作为损失函数。
目前,交叉熵损失函数是卷积神经网络中最常使用的分类损失函数,它可以有效避免梯度消散。在二分类情况下也叫做对数损失函数。
-
softmax损失函数 $$ L(Y|f(x)) = -\frac{1}{n} \sum_{i=1}^n Y_i \times log \frac{e^{f_{Y_i}}}{\sum_{j=1}^c e^{f_j}} $$
-
Focal loss $$ FE = \begin{cases} -\alpha(1-p)^\gamma log(p) \qquad \quad y = 1 \\\ -(1 - \alpha)p^\gamma log(1-p) \quad y = 0 \end{cases} $$
优化器
优化器就是在深度学习反向传播过程中,指引损失函数(目标函数)的各个参数往正确的方向更新合适的大小,使得更新后的各个参数让损失函数(目标函数)值不断逼近全局最小。
- SGD优化器(随机梯度下降法,易受噪声影响,可能陷入局部最优解)
$$ \omega_{t+1} = \omega_t - \alpha \cdot g(\omega_t) $$
$\alpha$为学习率,$g(\omega_t)$ 为$t$ 时刻对参数$\omega_t$ 的损失梯度。
优点:
-
每次只用一个样本更新参数,训练速度快
-
随机梯度下降所带来的波动有利于优化的方向从当前的局部极小值点跳到另一个更好的局部极小值点,这样对于非凸函数,最终收敛于一个较好的局部极值点,甚至全局极值点。
缺点:
- 当遇到局部最优点或鞍点时,梯度为0,无法继续更新参数
- 沿陡峭方向震荡,而沿平缓维度进展缓慢,难以迅速收敛
- SGD+Momentum优化器(引入动量,抑制样本噪声的干扰)
$$ v_t = \eta \cdot v_{t-1} + \alpha \cdot g(\omega_t) \\\ \omega_{t+1} = \omega_t - v_t $$
$\alpha$为学习率,$g(\omega_t)$ 为$t$ 时刻对参数$\omega_t$ 的损失梯度,$\eta(0.9)$ 为动量系数。
- 加入了动量因素,缓解了SGD在局部最优点无法持续更新的问题和震荡幅度过大的问题,但并没有完全解决,当局部沟壑比较深,动量加持用完了,依然会困在局部最优里来回振荡。
- Adagrad优化器(自适应学习率,二阶动量)
$$ s_t = s_{t-1} + g(\omega_t) \cdot g(\omega_t) \\\ \omega_{t+1} = \omega_t - \frac{\alpha} {\sqrt{s_t + \varepsilon}} \cdot g(\omega_t) $$
$\alpha$为学习率,$g(\omega_t)$ 为$t$ 时刻对参数$\omega_t$ 的损失梯度,$\varepsilon(10^{-7})$ 为防止分母为零的小数。学习率下降过快容易未收敛就停止训练
- RMSProp优化器(自适应学习率)
$$ s_t = \eta \cdot s_{t-1} + (1-\eta) \cdot g(\omega_t) \cdot g(\omega_t) \\\ \omega_{t+1} = \omega_t - \frac{\alpha} {\sqrt{s_t + \varepsilon}} \cdot g(\omega_t) $$
$\alpha$为学习率,$g(\omega_t)$ 为$t$ 时刻对参数$\omega_t$ 的损失梯度,$\eta(0.9)$ 控制衰减速度,$\varepsilon(10^{-7})$ 为防止分母为零的小数。
- Adam优化器(自适应学习率)
$$ m_t = \beta_1 \cdot m_{t-1} + (1 - \beta_1) \cdot g(\omega_t) \qquad一阶动量 \\\ v_t = \beta_2 \cdot v_{t-1} + (1 - \beta_2) \cdot g(\omega_t) \cdot g(\omega_t) \quad二阶动量 \\\ \hat{m_t} = \frac{m_t}{1 - \beta^t_1} \quad \hat{\frac{v_t} {1 - \beta^t_2}} \\\ \omega_{t + 1} = \omega_t - \frac{\alpha} {\sqrt{\hat{v_t} + \varepsilon}} \hat{m_t} $$
$\alpha$为学习率,$g(\omega_t)$ 为$t$ 时刻对参数$\omega_t$ 的损失梯度,$\beta_1(0.9)$、$\beta_2(0.999)$ 控制衰减速度,$\varepsilon(10^{-7})$ 为防止分母为零的小数。
- 通过一阶动量和二阶动量,有效控制学习率和梯度方向,防止梯度的振荡和在鞍点的静止。
- 可能错过全局最优解。自适应学习率算法可能会对前期出现的特征过拟合,后期才出现的特征很难纠正前期的拟合效果。后期Adam的学习率太低,影响了有效的收敛。
评估指标–F1分数
二分类:

阳性样本的真实数量:$TP + FN$
阴性样本的真实数量:$FP + TN$
$Precision$ (精确率,又称查准率)(值越高表示误诊数越低): $$ Precision = \frac {TP} {TP + FP} $$ $Recall$ (召回率,又称查全率)(值越高表示漏掉的病人越少): $$ Recall = \frac {TP} {TP + FN} $$ $Accuracy$ (准确率)(正确的样本占样本总数的比例): $$ Accuracy = \frac {TP + TN} {TP + FN + FP + TN} $$ $F1分数$ (综合考虑了精确率和召回率,认为他们同等重要): $$ F1 = 2 \times \frac {Precision \times Recall} {Precision + Recall} $$ 多分类问题:
-
微观: $$ (查准率) \quad microP = \frac {TP_1 + TP_2} {TP_1 + FP_1 + TP_2 + FP_2} $$
$$ (查全率) \quad microR = \frac {TP_1 + TP_2} {TP_1 + FN_1 + TP_2 + FN_2} $$
$$ microF1 = 2 \times \frac {microP \times microR} {microP + microR} $$
-
宏观: $$ (查准率) \quad macroP = \frac {Precision1 + Precision2} {2} $$
$$ (查全率) \quad macroR = \frac {Recall1 + Recall2} {2} $$
$$ macroF1 = 2 \times \frac {macroP \times macroR} {macroP + macroR} $$
-
“评估指标的选择”
当类别的分布相似时,可以使用准确率,当类别的分布不平衡时,F1分数是更好的评估指标。
图像处理中的卷积神经网络
LeNet模型(1998)
由Yann Le Cun于1998年提出,奠定了卷积神经网络的基础,由两个卷积层、两个全连接层和一个输出层组成。激活函数采用softmax,池化层采用平均池化。该模型早期主要用于手写字符的识别和分类。

ALexNet模型(2012)
- 首次利用GPU进行网络加速训练
- 使用了ReLu激活函数,使用最大池化方法
- 使用了LRN局部相应归一化
- 在全连接层的前两层使用了Dropout随机失活神经元,减少过拟合

过拟合根本原因是特征维度过多,模型假设过于复杂,参数过多而训练数据过少,噪声多,导致拟合的函数完美的预测了训练集而对测试集预测结果差。
卷积计算公式:
$$ N = \frac {(W - F + 2P)} {S} + 1 $$
AlexNet 网络的具体实现
原图输入224x224 实际上进行了随机裁剪,实际大小为227x227
|
|
GoogleNet模型(2014)
- 通过引入Inception模块来增加网络宽度
- 引入1x1的卷积层来压缩通道数量,降低计算量,从而进一步增加网络深度
- 添加两个softmax辅助分类器,缓解梯度消失现象
Inception就是把多个卷积或池化操作放在一起组装成一个网络模块。
VGGNet模型(2014)
- 使用多个3x3小尺寸卷积核和池化层构造深度卷积
- 在最后使用三层全连接层,用最后一层全连接层的输出作为分类的预测
- 成功证明了增加网络的深度,可以更好的学习图像中的特征模式

VGG16 网络的具体结构
|
|
SSD模型(2016)
SSD是基于一个前向传播反馈的CNN网络,属于one-stage类型。
- 对多尺度特征图进行检测
- 设置不同长宽比的先验框

基本的SSD模型是在VGG网络模型的基础上构建的,通过融合不同卷积层的特征图来增强网络对特征的表达能力,采用多尺度卷积检测的方法来进行目标检测其结构如图所示:
该模型基于VGG模型(改进版)来提取特征,将各级的卷积特征图作为该一级的特征表示,不同卷积级别的图像卷积特征描述了不同的语义,卷积层越深表达的图像特征信息级别越高。SSD模型中特征的提取采用的是逐层提取并抽象化的思想,低层的特征主要对应于占比较小的目标,高层的特征主要对应于占比较大的目标的抽象化的信息。 基本的SSD模型通过金字塔特征层进行特征提取,且各特征层之间相互独立,没有目标信息的相互补充,低特征层仅有Conv4_3层用于检测占比小的目标因而在缺乏充足的特征信息的情况下存在特征提取不充分的问题,因而导致对小型目标的识别效果一般。

SSD 网络的具体结构:
|
|
总结而言,SSD是把一张图片划分为不同的网格,当某一物体的中心点落在这个区域,这个物体就由这个网格来确定。
MobileNet(2017)
MobileNetV1

- Deptwise Convolution(深度可分离卷积)(大大减少运算量和参数数量)
标准的卷积网络结构:

深度可分离卷积网络结构:

当输入特征图的 shape 是$D_F \times D_F \times M$,其中 $M$ 为通道数,输出特征图的 shape 为$D_G \times D_G \times N$,通道数为 $N$ ,标准卷积核的尺寸为$D_k \times D_k \times M$时,卷积核的参与个数为 $D_k \cdot D_k \cdot M \cdot N$ 。深度可分离卷积一共分为两个步骤的卷积,其中 Depthwise Convolution 的卷积核为$D_k \times D_k \times 1$, Pointwise Convolution 的卷积核为$1 \times 1 \times M$。那么可以得出如下结论:
标准卷积的运算量: $$ D_k \cdot D_k \cdot M \cdot N \cdot D_F \cdot D_F = D_F \cdot D_F \cdot M \cdot (D^2_K \cdot N) $$ 深度可分离卷积的运算量: $$ D_k \cdot D_k \cdot M \cdot D_F \cdot D_F + M \cdot N \cdot D_F \cdot D_F = D_F \cdot D_F \cdot M \cdot (D^2_K + N) $$ 运算量对比: $$ \frac {D_F \cdot D_F \cdot M \cdot (D^2_K + N)} {D_F \cdot D_F \cdot M \cdot (D^2_k \cdot N)} = \frac {1} {N} + \frac {1} {D^2_K} $$
深度可分离卷积的tensorflow代码实现:
|
|
-
“Conv2D 和 Depthwise_conv2D的区别”
-
Conv2d在每个通道上卷积,然后求和,Depthwise_conv2D卷积,不求和。
-
Depthwise_conv2D的输出维度和输入维度始终是一致的。
标准卷积 深度可分离卷积 运算特点 每个卷积核的通道与输入通道相同,每个通道单独做卷积运算然后相加 DW卷积:一个卷积核只有一个通道,单独负责一个通道
PW卷积:将上一步的特征图在通道方向上进行扩展 -
- 超参数 $\alpha$ $\rho$
- $\alpha$ 宽度系数,对网络中每一层卷积的通道数乘以 $\alpha$ 取值范围[0,1],比较典型的值为1、0.75、0.5、0.35
$$ 计算量: \qquad D_k \cdot D_k \cdot \alpha M \cdot D_F \cdot D_F + \alpha M \cdot \alpha N \cdot D_F \cdot D_F $$
- $\rho$ 分辨率系数,只改变网络的计算量而不影响网络的参数量
$$ 计算量: \qquad D_k \cdot D_k \cdot \alpha M \cdot \rho D_F \cdot \rho D_F + \alpha M \cdot \alpha N \cdot \rho D_F \cdot \rho D_F $$
DepthWise部分的卷积核容易废掉,即卷积核参数大部分为零。(很重要的一个原因是因为 ReLU 激活函数对0值的梯度是0,后续无论怎么迭代这个节点都不会恢复,即“废掉了”)
-
“你知道吗?”
深度可分离卷积将一个标准卷积分割成了两个卷积(逐深度,逐点),因此减小了参数量,对应也减小了总计算量。 深度可分离卷积总计算量变小了,但是深度可分离卷积的层数变多了。
GPU是并行处理大规模数据(矩阵内积)运算的平台,而CPU则更倾向于对数据串行计算。
因此影响GPU总运算时间的主导因素一般是网络的层数。
而影响CPU总运算时间的主导因素是总计算量。
所以才会出现MobileNet在某些计算能力有限的CPU平台上速度竟然高于某些GPU平台上的速度。
MobileNet的tensorflow代码实现:
|
|
MobileNet v2

-
Inverted Residuals(倒残差结构)
倒残差结构是从ResNet中的残差结构而来的。ResNet中Residuals结构中,先用1x1的卷积实现了降维,然后通过3x3卷积,最后通过1x1卷积实现升维,即两头大中间小。
而在MobileNetV2中,先用1x1的卷积升维,然后将3x3卷积换为3x3DW卷积,再用1x1的卷积实现降维,即两头小中间大。
MobileNetV2的倒残差结构示意图:
ReLU6激活函数: $$ y = ReLU6(x) = min(max(x, 0), 6) $$
-
Linear Bottlenecks(线性瓶颈层)
作者发现当信息从高维空间经过非线性映射到低维空间时,会发生信息坍塌,所以在倒残差结构进行降维操作的时候,使用了线性激活函数(实现方式就是不使用激活函数)。
“思考”
之所以使用倒残差结构,和线性瓶颈层,是因为作者通过数学证明的方式,得出了在降维过度时,ReLU会造成大量的信息丢失,即升维之后更容易保持可逆
MobileNetV2的tensorflow实现:
|
|
待续未完。。。