【Python机器学习】卷积神经网络(CNN)

卷积神经网络(CNN)得名于在数据样本上用滑动窗口(或卷积)的概念。

卷积在数学中应用很广泛,通常与时间序列数据相关。它是用一个可视化盒子在一个区域内滑动,如下图所示:

构建块

卷积神经网络最早出现在图像处理和图像识别领域,它能够捕捉每个样本中数据点之间的空间关系,也就能识别出图像中是猫还是狗。

卷积网络,也称为convnet,不像传统的前馈网络那样对每个元素(图中的像素)分配权重,而是定义了一组在图像上移动的过滤器(也称卷积核、滤波器或特征检测器)。

在图像识别中,每个数据点的元素可以是黑白图像中的每个像素点,取值是1(on)或0(off)。也可以是灰度图像中每个像素的强度,或者彩色图像中每个像素的每个颜色通道的强度。

卷积核会在输入样本中进行卷积或滑动。卷积核窗口大小的参数由模型构建器选择,并且高度依赖数据内容。不过其中有一些共性,在图像数据中,通常会看到窗口大小为3*3(3,3)像素。

步长

在滑动阶段,移动的距离是一个参数,一般不会超过卷积核宽度,每个快照通常都与相邻快照由重叠的部分。

每个卷积"走"的距离称为步长,通常设置为1。只移动1个像素(或其他小于卷积核宽度的距离)将使进入卷积核的不同输入在一个位置和下一个位置之间出现重叠。如果由于步长太大而使卷积核之间没有重叠,就会失去像素(在NLP中是词条)与相邻像素之间的"模糊"效果。

这种重叠有一些有趣的特性,特别是在查看卷积核如何随时间变化的时候,这些特性非常明显。

卷积核的组成

卷积核由两部分组成:

  • 一组权重
  • 一个激活函数

卷积核通常是3*3,当然也有其他大小和形状。

当卷积核在图像上滑动时,每次前进一个步长,得到当前覆盖像素的快照,然后将这些像素的值与卷积核中对应的权重相乘。

假设使用的是3*3卷积核,从左上角开始,第一个像素(0,0)乘以卷积核第一个位置(0,0)上的权重,第二个像素(0,1)乘以位置(0,1)上的权重,以此类推。

然后对像素和权重(对应位置)的乘积求和,并传递到激活函数(通常选择ReLU函数,线性修正单元)中,如下图:

在上面两张图中,是位置i上的像素值,是ReLU激活函数的输出z_0=max(sum(x*w),0)或者。该激活函数的输出将被记录在输出图像中的一个位置上。卷积核滑动一个步长,处理下一个快照,并将输出值放在上一个输出值的旁边。

在一个层中有多个这样的卷积核,当它们在整个图像上进行卷积时,会各自创建一个新的"图像"------一个被"过滤"后的图像。假设有n个卷积核,在经过这个处理之后,将得到n个经过过滤的新图像。

填充

如果从输入图像的左上角开始一个3*3的卷积核,每次移动一个像素,当卷积核的最右侧边缘到达输入图像的最右侧边缘时停止,那么输出的"图像"将比原图形窄两个像素。

Keras提供了处理这个问题的工具。第一个策略是忽略输出维度变小的问题。在Keras中,可以设置参数padding='valid'。使用这种方法时,需要注意下一层输入的维度。这种策略的缺点是重叠位置上的内部数据点被多次传递到每个卷积核丧,原始输入的边缘数据将被欠采样。在比较大的图像上,这可能不是问题,但是如果把这个概念应用到X数据上,例如,在一个10个单词的数据集上进行欠采样,则可能会极大地改变输出结果。

另一个策略称为填充,即向输入数据的外部边缘提供足够多的数据,使边缘上的第一个数据点可以被视为内部数据点进行处理。这种策略的缺点是向输入数据中添加了可能不相关的内容,导致偏离了输出结果。具体做法参考:

python 复制代码
from keras.api.models import Sequential
from keras.api.layers import Conv1D

model=Sequential()
model.add(Conv1D(
    filters=16,
    kernel_size=3,
    padding='same',
    activation='relu',
    strides=1,
    input_shape=(100,300)
))

还有一种策略,例如在预处理过程中通过模拟已存在的边缘数据点来预测要填充位置上的值。不过这种策略危险性较大,NLP应用中一般不使用。

卷积流水线

现在有n个卷积核和n个新图像。和大多数神经网络应用一样,我们从一个已标注的数据集开始,任务目标也类似:预测一个给定新图像的标签。最简单的方法是将每个过滤后的图像串起来并输入到前馈层。

不管在网络中添加了多少层(卷积层或其他层),一旦得到一个最终输出,就可以计算出误差并通过网络进行反向传播该误差。

因为激活函数是可微的,所以可以像之前一样反向传播并更新各个卷积核的权重。然后网络会学习到需要什么样的卷积核才能为给定的输入获得正确的输出。

这个过程可以视为神经网络在学习检核和提取信息,以便让后面的层能更容易地进行处理。

学习

就像所有神经网络一样,卷积核本身会以初始化为接近零的随机值的权重开始。在最初的几轮迭代训练中,它只是噪声。

但是构建的分类器会根据各个输入数据,从期望标签中获得一定的误差值,并通过激活函数将输入数据反向传播给卷积核。对于误差值的反向传播,我们还需要计算误差对输入权重的导数。

当卷积层刚出现时,它用的是上层梯度对输入权重的导数。这个计算和正常的反向传播类似,对于给定训练样本,卷积核权重会在多个位置上输出对应的结果。

对于一个给定卷积核的权重,梯度是前向传播过程中卷积的每个位置上梯度的和。两个求和及多个叠加式如下:

这一概念与常规的前馈网络基本相同,即计算出每个特定权重对系统总体误差的共线,然后再来决定如何更好地调整权重,使其能够在后面的训练样本上尽量减小误差。

相关推荐
AAA_bo11 分钟前
liunx安装canda、python、nodejs、git,随后部署私有网页内容提取工具--JinaReader全攻略
linux·python·ubuntu·typescript·aigc·python3.11·jina
Lucky小小吴1 分钟前
java代码审计入门篇——Hello-Java-Sec(完结)
java·开发语言
JoannaJuanCV8 分钟前
自动驾驶—CARLA仿真(20)manual_control demo
人工智能·机器学习·自动驾驶·carla
csbysj20208 分钟前
XML 技术
开发语言
最晚的py9 分钟前
聚类的评估方法
人工智能·算法·机器学习
清晓粼溪9 分钟前
Java登录认证解决方案
java·开发语言
小徐Chao努力11 分钟前
Go语言核心知识点底层原理教程【变量、类型与常量】
开发语言·后端·golang
锥锋骚年11 分钟前
go语言异常处理方案
开发语言·后端·golang
沐知全栈开发12 分钟前
JSP 自动刷新技术详解
开发语言
特立独行的猫a13 分钟前
C++使用Boost的Asio库优雅实现定时器与线程池工具类
开发语言·c++·线程池·定时器·boost·asio