5.基础算子及卷积神经网络
4.1 基础算子
函数的定义域为一个数集,值域也为一个数集,即函数是数值到数值的映射。
泛函的定义域为函数集,值域为是实数集,即泛函是函数到数值的映射。
算子的定义域为函数集,值域为函数集,即算子是函数到函数的映射。
在深度学习是由一个个计算单元组成的,这些计算单元我们称为算子(Operator),**算子在神经网络中表示对应层的计算逻辑。**例如:在深度学习中对tensor(矩阵)的操作,如线性运算,加权求和等数学函数计算。
对于激活函数,如sigmoid函数、符合函数等,我们称为用作激活函数的算子。
下面演示一些基础的算子,帮助理解算子是什么?
例如微分算子,是使函数y处理变成y^′,其表达式为:
这表示对函数y求了一次导,同理可以将D(y)微分算子再求一次导:
由此归纳总结出:
其中n表示对函数y求导了n次。
下面以求和算子进行举例说明算子在神经网络中是如何运用的,在之前我们学习到了神经元会接收n个输入x_i,进行一些数学运算,再产生一个输出y。
如上图所示,求和算子就是接收n个输入后,将每个输入乘以其权值后相加,相加后的值为总输入,将总输入作为参数X传给激活函数,公式为:X=∑_(i=1)^n[x_1+x_2+…+x_n ],经过激活函数输出Y。
4.2 卷积神经网络
神经网络有许多算子构成的网络框架,典型的神经网络如下图的卷积神经网络,其中至少有一层是由卷积算子构成的网络
卷积神经网络(Convolutional Neural Networks)是人工神经网络的一种特殊类型,在其至少一层中使用称为卷积的数学运算代替通用矩阵乘法。它们专门设计用于处理像素数据,并用于图像识别和处理。
一个卷积神经网络主要由以下5层组成:
•数据输入层/ Input layer
•卷积计算层/ CONV layer
•池化层 / Pooling layer
•ReLU激励层 / ReLU layer
•全连接层 / FC layer
4.3 卷积算子
4.3.1 为什么需要卷积?
在机器学习中输入都是以高维数据为主,在之前我们使用简单的线性学习器,如下图所示:
上述是各个维度线性可分的情况,我们可以通过简单的直线或者将样本进行分类。但如果样本的分布出现如下图所示的情况,样本变成了线性不可分了。
下图可以看出来在2维中我们不能使用一条直线将红蓝样本分类,但我们还 是想两个样本进行分类,所以我们将样本映射到3维上,如上图中3维所示,原本在2维上不可分的样本,在3维就可以使用一个平面将样本分开,所以我们通过一个映射函数将样本从n维映射到n+1维或者更高维度,使得原本线性不可分的问题变成线性可分,以解决样本分类。
所以我们为了去求解分类问题,我们如何去升维呢?
假设H为特征空间,如果存在一个从低维空间X和高维空间H的映射,映射过程记为∅(x),则有:
使得对所有的x,y∈X,函数K(x,y)满足条件
其中函数K(x,y)被称为核函数,∅(x)称为x的映射函数,∅(y)称为y的映射函数,∅(x)∙∅(y)是∅(x)和∅(y)的内积。
将原始空间中的向量作为输入向量,并返回特征空间(转换后的数据空间,可能是高维)中向量的点积的函数称为核函数。
核函数就是为了找到样本的分割函数而产生的能使样本从低维空间映射到高维空间,使得原本在低维空间中不可分的数据在高维中可分。
4.3.2 图像卷积
对于图像的卷积,则输入是二维的图像I,核函数为K,因为m,n的取值范围相对较小,在许多神经网络库中还会实现一个互相关函数为:
在许多机器学习库中的互相关函数也称为卷积。所以我们知道卷积过程就是图像乘核函数。
卷积完成后可以在高维空间将图像中的像素样本变成可分的,即提取特征值。
卷积层(conv)是使用卷积核(核函数)来提取图像的特征信息并将其输入到神经网络中,我们可以通过重复的卷积操作来获得图像的在不同层次的特征,从而减少源图像中各种噪声的污染。如图所示,卷积中运算过程由二维数字矩阵卷积核对原图像进行卷积,具体步骤为:
1.在图像的某个位置覆盖卷积核;
2.将卷积核中的值与图像中的对应像素矩阵的值相乘;
3.将步骤2的乘积结果相加,得到的和为输出图像中的目标像素值;
4.对图像的全部位置重复上述操作。
4.3.3 卷积与互相关
我们从上一小节学习到图像的卷积过程就是源图像与核函数对应像素值相乘,并将乘积结果进行累加。可以发现其实这个操作直观上来看更像加权求和的感觉,那么为什么叫做卷积呢?目前图像卷积是根据卷积的思想而来的相关运算,所以在神经网络中会实现互相关函数。
那么这里的**“互”**是谁和谁相关呢?我们以3×3的卷积核来看,原图像经过一个卷积核之后,输出一个值,那么这个值就是源图像中“中间像素”与周围一圈像素的关系。也就是说,卷积核帮助我们找这两者的关系,分别为两种:另一种是周围像素对中间像素的关系影响;另一种是中间像素与周围像素的关系影响。所以卷积实际上是分为两种操作,分别是:
- 考虑周围像素如何对当前中间像素点产生影响的。
- 当前中间像素点对周围像素的试探和选择。
4.3.4 卷积处理图像
那么下面我们来看看哪一种是我们前面用于提取特征值的操作。
周围像素对中间像素的影响:我们以图像模糊为例,带大家了解周围像素如何对中间像素产生影响的。我们使用OpenCV库的实现一个简单的均值模糊。
#导入opencv模块
import cv2 as cv
#读取当前目录图像,支持 bmp、jpg、png、tiff 等常用格式
img = cv.imread("test.jpg")
#创建一个input窗口用于显示图像
cv.namedWindow("input")
#在input窗口中展示输入图像
cv.imshow("input",img)
#图像均值模糊处理,使用3*3的卷积核处理,处理结果图像存储在blur
blur = cv.blur(img, (3,3), 0)
#创建一个Output窗口用于显示图像
cv.namedWindow("Output")
#在Output窗口中展示输入图像
cv.imshow("Output",blur)
#创建的窗口持续显示,直至按下键盘中任意键
cv.waitKey(0)
#释放窗口
cv.destroyAllWindows()
输入和经过均值模糊处理后的图像,如下所示:
可以通过两张图片看出来,经过均值模糊后的图像与原图像对比更加模糊了,减小了噪声。那么这个均值模糊也是和我们前面说的一样,原图像经过一个卷积核进行处理,处理后的图像输出即为卷积后的图像。下面我们来看一下均值模糊是如何实现这一个模糊过程的。
我们这里就不以公式的角度理解均值模糊,我们根据图像像素值的角度来看。首先我们需要清楚,图像模糊的本质是处理图像中与周围差异较大的点,将其像素值调整为与周围点像素值近似的值。
均值模糊:每一个像素点都取周边像素的平均值后,如果中间值大于平均值,就降低中间值;如果中间值小于平均值,就升高中间值。在数值上就表现出平滑的效果,在图像中就表现为模糊的效果。
如果用坐标的形式表示中间像素和周围像素,可如下所示:
所以程序中均值模糊中的卷积操作是:
1.在图像的某个位置覆盖卷积核,归一化卷积核为
2.将卷积核中的值与图像中的对应像素矩阵的值相乘;
3.将步骤2的乘积结果相加,得到的值为输出图像中的目标像素值;
4.对图像的全部位置重复上述操作。
那么下面我们通过放大输入图像和经过均值模糊的输出图像,来看一下均值模糊的计算过程。
我们通过上图知道输入图像黄色框中的RGB值和输出图像黄色框中的RGB值,两个黄色框是图像中的同一位置。计算过程如下:
-
为更好的展示过程,我们单独计算RGB通道,那么卷积核覆盖位置的原图像RGB值分别为:
-
将RGB三通道的值分别与卷积核k相乘
- 再将乘积结果相加,得到的值为输出图像中的目标像素值
- 目标像素RGB值为:
我们对比图像中显示的RGB和我们计算出来的一致。所以卷积在图像处理中操作可以用于考虑周围像素对中间像素的影响,根据周围像素的值来计算计算中间像素的值,从而实现 图像模糊的效果,降低图像噪点。
4.3.5 卷积提取图像特征
前面我们学习了考虑周围像素对中间像素的影响的卷积可以去实现一些对图像的处理,那么卷积又是如何实现特征提取的呢?
以下示例来源国外作者Charles Crouspeyre的《卷积神经网络是如何工作的?》
假设我现在需要识别下面黑白图像中的是X还是O,由于图像中的X和O处于不同位置,如果通过我们人眼是可以判断出对应图像里的是X和O的。
如果电脑去判断两张X图像,其中X的位置不同,如果使用传统的方法比较图像中的元素值,可以电脑就可以得出,两张图像不一致,且无法判断图像中有X。
所以我们需要使用卷积神经网络来对这些图像处理,就可以知道传入的图像是X还是O,那么卷积神经网络中的卷积是如何处理这些图像的?
在开始前我们先观察这两张图像中有哪些相同特征,我们可以看到他们两个有些局部特征是相同的,如下图中红黄蓝框所示:
可以看到这些局部特征是有相似的,下面根据这些局部特征,我们创建三个3*3的卷积核,如下所示:
可以看到这个特征可以和图像X中特征对应上,如下图所示:
那么现在我使用第一个卷积核来进行卷积操作,计算如下图中绿框位置,卷积后的值输出在下图中右边黄色框中。
继续使用与上图相同的卷积核,计算下图中绿框位置,卷积后的结果输出在下图中右边黄色框中。
计算完成后得到卷积后的图像矩阵图下图所示:
我们可以看到一个现象,经过这个卷积核之后会,卷积结果图像得到的特征是一条从左上到右下的对角线,他与图像中X的从左到右向下的对角线相匹配,所以我们可以看到在结果图像中所有高的值,都在这条对角线上,这条对角线与卷积核的匹配比其他地方与卷积核的匹配的匹配更好。
那么下面我们分别来看三个卷积核后的卷积结果,如下图所示:
用中间的X卷积核和从斜向上的卷积核,经过卷积后得到特征出现的位置和我们期望的特征是一致的,也就是说可以提取到原图像中X的特征值。那么在神经网络中使用一堆卷积核对图像进行处理并提取特征,这就称为卷积层。
通过上图我们又可以看出一个规律,假设输入图像为X,卷积核为w,偏置为b,那么卷积输出的结果为Y,则有:
上述式子中卷积核W和偏置b是可学习的参数,即:可通过训练改变的参数。
4.3.6 一维卷积和二维卷积
我们已经知道卷积的作用,那么如何使用pytorch深度学习框架来实现卷积操作?
一维卷积实现
下面是使用pytorch实现的一个例子,展示一维的tensor经过一维卷积后的结果矩阵。
import torch
from torch import nn
#设置卷积函数,输入通道为1,输出通道为1,核函数大小为3,步长为3,偏置为0
conv1 = nn.Conv1d(in_channels=1,out_channels=1,kernel_size=3,stride=3,bias=0)
input = torch.Tensor([[1,2,3,4,5,6,7,8,9]])
print(input)
nn.init.constant_(conv1.weight, 1)#核函数参数设置为1
print(conv1)
output = conv1(input)
print(output)
输出结果:
输出信息为:
tensor([[1., 2., 3., 4., 5., 6., 7., 8., 9.]])
Conv1d(1, 1, kernel_size=(3,), stride=(3,), bias=False)
tensor([[ 6., 15., 24.]], grad_fn=<SqueezeBackward1>)
二维卷积实现
下面是使用pytorch实现的一个例子,展示二维的tensor经过二维卷积后的结果矩阵。
import torch
from torch import nn
#设置卷积函数,输入通道为1,输出通道为1,核函数大小为3,步长为1,偏置为0
conv2 = nn.Conv2d(in_channels=1,out_channels=1,kernel_size=3,stride=1,bias=0)
input = torch.Tensor([[[1,1,0,0,1,1],[0,0,1,0,1,0],[0,1,1,1,0,0],[0,1,0,0,1,1],[1,0,1,1,0,0],[1,1,1,0,0,1]]])
print(input)
nn.init.constant_(conv2.weight, 1)#核函数参数设置为1
print(conv2)
output = conv2(input)
print(output)
输出结果:
tensor([[[1., 1., 0., 0., 1., 1.],
[0., 0., 1., 0., 1., 0.],
[0., 1., 1., 1., 0., 0.],
[0., 1., 0., 0., 1., 1.],
[1., 0., 1., 1., 0., 0.],
[1., 1., 1., 0., 0., 1.]]])
Conv2d(1, 1, kernel_size=(3, 3), stride=(1, 1), bias=False)
tensor([[[5., 5., 5., 4.],
[4., 5., 5., 4.],
[5., 6., 5., 4.],
[6., 5., 4., 4.]]], grad_fn=<SqueezeBackward1>)
二维卷积实现过程
4.4 池化层
4.4.1 最大池化与均值池化
池化层(pooling)又称为下采样层,池化层的卷积核只是对应位置的最大值和平 均值。池化与卷积操作不同主要表现在矩阵运算规律的差异。其主要功能是保持特征不变性,包括平移、旋转和尺度。利用池化进行特征降维,降低了卷积层对冗余信息的敏感性,提取了重要特征值。
池化层的每一次操作都是对输入图像数据,利用一个固定形状窗口中的元素的计算输出,其中该运算有最大池化和平均池化。
最大池化是在二维中的最大池化,窗口从输入数组的左上角开始,按照从左到右和从上到下的顺序向下滑动。当最大池化窗口滑动到某个位置时,窗口中输入子数组的最大值是输出数组中相应位置的元素。
均值池化是池化特征图的局部感受,当池化平均窗口滑动到某个位置并返回其集合平均时,窗口中输入子数组的平均值是输出数组中相应位置的元素。池化操作过程如图所示。
4.4.2 卷积网络中的最大池化
我们回到3.3.5中的例子,我们已经经过卷积之后提取到原图像中X的特征值,如下图所示:
那么下面我们对着卷积提取的特征图像进行最大池化(Max Pooling)操作,如下图所示:
可以看到经过最大池化后我们得到了一个更小的图像,但是图像中仍然保存这卷积提取的特征值在特征图像的对角线上。也就是我们将原本7*7
的特征图像,降维为4*4
的特征图像,大小只有原来的一半。
小思考:如果我们的图像比较大,分辨率比较高,那么卷积操作提取特征之后,图像尺寸还是很大,那么这很不利于我们部署在一些嵌入式设备中,这种图像像素缩小,还能保存特征的方式是十分有用的。
如果你想寻找图像中的特征,它可能会向左一点或者向右一点,或者旋转一点,但特征依然可以被提取,可以对所有的经过卷积的图像进行最大池化,可获得卷积之后的更小的特征图像。
4.5 RELU 激励层
4.5.1 线性整流激活函数
RELU激励层,也称非线性激活层。 RELU激励层使用线性整流激活函数,该函数可以保留大于0的值,即保 留特征比较好的值,将特征小于0的值舍去。
下面展示线性整流函数(Rectified Linear Unit)的函数公式:
relu函数图像为:
ReLU激活函数的主要优点是:
•卷积层和深度学习:它们是卷积层和深度学习模型训练中最常用的激活函数,可以使网络有非线性表达,增加网络拟合能力。
•计算简单:整流函数实现起来很简单,只需要一个max()函数。
•代表性稀疏性:整流器函数的一个重要优点是它能够输出一个真正的零值。
4.5.2 卷积网络中的RELU层
RELU函数由于其导数在正区间且恒为1,可以避免梯度的随着网络层数的增加而消失的问题,所以我们在网络层的任意位置都可以使用它作为激活函数。我们回到4.3.5中的例子,我们已经经过卷积之后提取到原图像中X的特征值,我们对卷积提取的特征值使用RELU激活函数处理,如下图所示:
通过上图我们看到RELU激活函数就是遍历图像中的所有负值的像素,将所有负值都变为0。当经过一次激活函数后会得到一个原来十分相似的图像。对所有图像都经过RELU激活函数处理后,即为RELU层
下面我们将卷积层、RELU层、池化层叠加使用,可得到如下所示结构:
我们用过上图了解到,图像输入卷积后,输出的卷积结果,传给RELU层进行处理,RELU层输出的结果,传给Pooling层进行池化操作,最后输出。多层网络的规律就是一个层的输出作为下一个层的输入。那么下面我们再次对网络进行堆叠,建立更多层的卷积层、RELU层、池化层,如下所示,对网络层进行深度堆叠。
当然,如果您的图像尺寸比较大,你还可以进行堆叠,堆叠成一个更多层的网络。每次图像经过卷积层之后都会获得特征图像,随着卷积层和池化层的层数增加,特征图像也会变得越来越小。
4.6 全连接层
4.6.1 全连接层核心公式
全连接层(full connection)是把每个结点连接到上层的所有结点,以合成从前端层提取的特征,并接受图片特征值的输入,进行训练,训练完成后就可对输入的特征值进行分类。
全连接的核心公式为:
其中:x为全连接层的输入矩阵,W为权重系数,b为偏置。
4.6.2 卷积网络中的全连接层
在卷积神经网络中,经过了卷积层、RELU层、池化层的特征提取后 ,最后一层网络需要使用到全连接层。以4.5.2中经过深度堆叠后的特征图像,经过全连接过程如下所示:
将现在经过多次过滤且尺寸大大减小的图像特征,分解出来并重新排列,放入一个列表中,对结果进行计算。可以把全连接形象的理解为,特征值中的每一个值就是一个人,原来特征值是排成方阵形式的,现在将他们一个一个拎出来,排成一排。让每一个人去对类别X和O进行投票,每个人都可以对X和O进行投票。
当我们输入图像含X时,每一个人为类别X的获得更多的票数,也就是说他们更倾向于这张图像是X图像。
当我们输入图像含O时,每一个人为类别O的获得更多的票数,也就是说他们更倾向于这张图像是O图像。
如果我们通过训练得到了全连接中合适的权重和偏置,如果我们的网络得到了一个新的输入图像,那么此时就会根据卷积池化RELU得到的结果,再次进行投票,如下所示:
我们再次对X和O进行投票,最终我们可以通过观察那个票数高,来判断输入的图像是X还是O。
当然,我们也可以像卷积、池化、RELU一样,可以叠加很多层,类似于下图所示:
所以我们的卷积神经网络可以设计成下图这样,经过卷积、池化、RELU后经过两层的全连接层,最终投票输出X和O的概率。
4.6.3 分布式特征映射
全连接层利用分布式特征表示将特征值映射到样本标记空间中,具体步骤简图如下所示:
(全连接层是把特征表示整合到一起,输出为一个值)
假设下面以一个检测人脸和猫的网络的简图,其中就演示了全连接神经网络,就是特征整合成一个值,这个值越大就证明检测的图像中有人脸或有猫,不论其在图像中的位置。
全连接层在整个网络中起到“分类器”的作用。如果说卷积层、池化层和激活函数等操作是将原始数据映射到隐层特征空间的话(特征提取+选择的过程),全连接层则起到将学到的特征表示映射到样本的标记空间的作用。换句话说,就是把特征整合到一起(高度提纯特征),方便交给最后的分类器或者回归。
4.7 训练与超参数
我们了解了卷积神经网络中的卷积层、池化层、全连接层,下面我们来看他们在整个卷积神经网络中的作用。
前面我们讨论了卷积神经网络中的卷积、池 化、RELU、全连接是如何提取特征,并把特征输出出来。这就需要有合适的权重和偏置值等需要通过训练找到合适参数。那么训练是如何更新参数的呢?这里就需要用到前面我们学习了的反向传播算法,反向传播就是利用全连接层最后输出的预测结果,计算误差来确定网络的调整和变化程度。
例如,我们如果得到的3.6.3中的预测概率X和O分别是0.93和0.35,我们已知正确值X和O应为1和0,那么我们就有以下表格:
predict value | actual value | Error | |
---|---|---|---|
X | 0.93 | 1 | 0.07 |
O | 0.35 | 0 | 0.35 |
Total | 0.42 |
使用梯度下降法获得最低误差,如下所示:
在不断训练中去调整卷积核、全连接权重等参数,看看误差如何变化,调整的量取决于有多大的误差;误差越大调整越大,误差越小调整的越小。就像小球在山上找下山的路一样,小球想沿着这个斜坡走下去,也就是沿着梯度找到最底部,因为最底部是误差最小的时候。
超参数是在网络开始学习过程之前设置值的参数,我们来看一下卷积神经网络中的超参数有哪些:
-
卷积层Convolution
- 卷积核的数量
- 卷积核大小
-
池化层Pooling
- 池化窗口尺寸
- 池化步长
-
全连接层Fully Connected
-
隐藏层神经元数量
-
下面展示一个卷积神经网络的交互式节点连接可视化网站:https://adamharley.com/nn_vis/