卷积神经网络的体系结构

1、机器如何看待图像

人脑是一个很强大的机器,我们每秒可以看到(捕获)多个图像并处理它们而不知道是如何完成的。但是,机器不是这样的。图像处理的第一步是理解,如何表示图像,以便机器能够读取它。

简单地说,每一个图像都是以特定的顺序排列的点(像素)的排列。如果改变一个像素的顺序或颜色,图像也会改变。让我们举个例子。假设,你想存储和读取一个写在图片上的数字4。

机器将基本上将该图像分解成像素矩阵,并在代表位置存储每个像素的颜色代码。在下面的表示中,数字1是白色的,256是最暗的绿色阴影(为了简化,我限制了示例只有一种颜色)。
在这里插入图片描述
一旦以这种格式存储图像,下一个挑战是使神经网络理解这种排列和模式。

2、我们如何帮助神经网络识别图像

通过某种方式排列像素来形成数字。
在这里插入图片描述
假设我们尝试使用一个全连接网络来识别它?识别它是做什么的?

一个全连接网络将这个图像作为一个阵列,通过扁平化,并考虑像素值作为特征来预测图像中的数字。当然,网络很难理解下面发生的事情。
在这里插入图片描述
即使是人类也不可能识别出这是数字4的表示。我们已经完全失去了像素的空间排列。

我们能做什么?让我们尝试从原始图像中提取特征,从而保留空间排列。

案例1

在这里,我们使用了一个权重乘以初始像素值。
在这里插入图片描述
肉眼很容易发现这是4。但是再一次把这个图像发送到一个全连接网络,我们必须使它变平。我们无法保持图像的空间排列。

在这里插入图片描述

案例2

现在我们可以看到,扁平化的图像完全破坏了它的排列。我们需要设计一种将图像发送到网络而不使它们变平并保持其空间布局的方法。我们需要发送2D/3D排列的像素值。

让我们试着一次取两个像素值,而不是只取一个。这将为网络提供一个很好的视角来了解相邻的两个像素是怎样的。现在我们一次取两个像素,相应地两个权重值。
在这里插入图片描述
我希望你注意到,图像现在从一个4列排列开始变成3列排列。因为我们现在一次移动两个像素(像素在每个运动中共享),所以图像变小了。我们使图像更小,我们仍然可以在很大程度上理解它是4。此外,我们要认识到的一个重要事实是,我们取两个连续的水平像素,因此这里只考虑水平排列。

这是从图像中提取特征的一种方法。我们能看到左边和中间部分,但是右边不是很清楚。这是因为以下两个问题:

  • 图像的左右角仅乘以一次的权重。
  • 由于权重值很高,而右边部分由于权重较低而略微丢失,所以仍然保留了左侧部分。

现在有两个问题,我们有两个解决办法。

案例3

遇到的问题是图像的左右角落只会被权重传递一次。我们需要网络像其他像素一样考虑角点。

我们有一个简单的解决方案来解决此问题 沿着权重运动的两侧放置零点。
在这里插入图片描述
可以看到,通过添加零保留了角落中的信息,图像尺寸也更大,在不希望图像尺寸减小的情况下可以使用这种方法。

案例4

我们试图解决的问题是右侧角落中的较小权重会降低像素值,从而使图片难以识别。我们可以在一个回合中将多个权重值放在一起。

权重值为(1,0.3)时的输出:
在这里插入图片描述
权重值为(0.1,5)时的输出:
在这里插入图片描述
这两个图像的组合版本会给我们一个非常清晰的画面。因此,我们所做的只是使用多个权重,而不是一个来保留关于图像的更多信息。最终的输出将是上述两张图像的组合版本。

案例5

到目前为止,我们已经使用了试图将水平像素放在一起的权重。 但在大多数情况下,我们需要保持水平和垂直方向的空间布局。 我们可以将权重作为一个二维矩阵,在水平和垂直方向上的像素组合在一起。 另外,请记住,由于我们已经进行了水平和垂直移动的权重,所以输出在水平和垂直方向上都降低了一个像素。
在这里插入图片描述

那么我们做了什么?

我们上面做的是试图通过使用图像的空间排列从图像中提取特征。对于网络来说,了解像素的排列方式对了解图像非常重要。 我们上面做的是了解卷积神经网络究竟是做什么的。我们可以采用输入图像,定义权重矩阵,并将输入卷积以从图像中提取特定特征,而不会丢失关于其空间排列的信息。

这种方法的另一大优点是它减少了图像中的参数数量。如上所述,与原始图像相比,卷积图像的像素较少。 这大大减少了网络训练所需的参数数量。

3、定义一个卷积神经网络

我们需要三个基本组成来定义一个卷积网络。

  1. 卷积层
  2. 池化层
  3. 输出层
3.1卷积层

在这一层,就是我们看到的案例五中的例子。假设我们有一个尺寸为6 * 6的图像。我们定义一个权重矩阵,从图像中提取某些特征。
在这里插入图片描述
我们已经将权重初始化为 3∗3 矩阵。 这个权重应当对每个像素都进行运算,以给出一个卷积输出。上面的值429是通过将权重矩阵的元素值与输入图像中加高亮的 3∗3 部分对应元素相乘后相加而获得的。

现在将 6∗6 图像转换为 4∗4 图像。想像权重矩阵就像绘画墙上的画笔,刷子首先水平绘制墙壁,然后下降并水平绘制下一行。当权重矩阵沿着图像移动时,再次使用像素值。 这基本上使卷积神经网络中的参数共享成为可能。

让我们看看在一个真实的图片上是怎样的。
在这里插入图片描述
权重矩阵的行为在图像中就像是过滤器,从原始图像矩阵中提取特定的信息矩阵。权重组合可能是提取边缘,另一个可能是量化特定的颜色,而也有可能只是模糊掉不需要的噪声。

学习权重以使损失函数最小化,类似于MLP。因此,从原来的图像中提取出一些特征来帮助网络进行正确的预测。当我们有多个卷积图层时,初始图层提取更多的泛型特征,而随着网络的深入,权重矩阵提取的特征越来越复杂,更适合于图像的识别与处理。

步长和填充的概念

在我们之前的案例中,过滤器或权重矩阵在整个图像上一次只移动一个像素。我们可以将它定义为超参数,就像我们希望权重矩阵如何在图像上移动一样。如果权重矩阵一次移动1个像素,我们称它为1的步长。让我们看看步长为2的例子。
在这里插入图片描述
正如你所看到的,随着我们增加步长值,图像的大小不断减小。 用零填充输入图像的零点为我们解决了这个问题。 我们还可以在图像周围添加多个零层,以防更高的步长值。
在这里插入图片描述
在用零填充图像后,我们可以看到图像的初始形状是如何保留的。这称为相同的填充,因为输出图像与输入大小相同。
在这里插入图片描述
这被称为相同的填充(这意味着我们只考虑输入图像的有效像素)。中间的 4∗4 像素将是相同的。 在这里,我们保留了更多来自边界的信息,并保留了图像的大小。

多个过滤器和激活图

需要记住的一点是,权重的深度尺寸与输入图像的深度尺寸相同。 权重延伸到输入图像的整个深度。 因此,使用单一权重矩阵的卷积会导致具有单一深度维度的卷积输出。在大多数情况下,而不是单个滤波器(权重矩阵),我们有多个卷积核一起应用。

每个滤波器的输出被堆叠在一起,形成卷积图像的深度维度。 假设我们有一个大小为 32∗32∗3 的输入图像。 我们应用10个大小为 5∗5∗3 的卷积核对其进行卷积,输出的维度为 28∗28∗10 。

你可以将它想象成 -
在这里插入图片描述
这个激活图是卷积图层的输出。

3.2池化层

有时当图像太大时,我们需要减少可训练参数的数量。然后期望在随后的卷积层之间周期性地引入合并层。 合并是为了减少图像的空间大小而完成的。 合并在每个深度维度上独立完成,因此图像的深度保持不变。 通常应用的最常见的池化形式是最大池化。

在这里插入图片描述
这里我们将步长设置为2,同时将尺寸合并为2。最大操作应用于卷积输出的每个深度维度。如您所见,在最大池操作后, 4∗4 卷积输出已变为 2∗2 。

让我们看看最大化池在实际图像上的显示方式。

在这里插入图片描述
正如你可以看到我已经采取了复杂的图片,并已应用最大池。最大的汇集图像仍保留有关它是街上汽车的信息。如果仔细观察,尺寸是否已减半。这有助于在很大程度上减少参数。

同样,其他形式的合并也可以应用,如平均合并或L2规范合并。

输出尺寸

在每个卷积图层的末尾,您可能会对理解输入和输出尺寸有些困惑。我决定采取这几行方式,使您能够识别输出尺寸。三个超参数将控制输出量的大小。

  • 过滤器的数量 - 输出体积的深度将等于应用的过滤器数量。请记住我们如何堆叠每个过滤器的输出以形成激活图。激活图的深度将等于过滤器的数量。
  • 步长 - 当我们跨越一个单一像素时,我们跨步向前。随着更高的步长值,我们一次移动大量的像素,从而产生更小的输出量。
  • 填充 - 这有助于我们保留输入图像的大小。如果只在原始图像周围添加一个填充的层数,并且步长为一,那么输出将保留原始图像的大小。

我们可以应用一个简单的公式来计算输出尺寸。 输出图像的空间大小可以计算为 ([W−F+2P]/S)+1 。 这里,W是输入体积大小,F是过滤器的大小,P是施加的填充数,S是步长数。 假设我们有一个大小为 32∗32∗3 的输入图像,我们应用10个大小为 3∗3∗3 的过滤器,单步和无零填充。

这里W = 32,F = 3,P = 0和S = 1。 输出深度将等于所用过滤器的数量,即10。

输出体积大小为 ([32−3+0]/1)+1=30 ,因此输出体积为 30∗30∗10 。

3.3输出层

经过多层卷积和池化后,我们需要以类的形式输出。卷积和池化层只是从原始图像中提取了特征, 然而想要生成最终的输出,我们需要在卷积层之后加入一个全连接层,并使全连接层的输出等于我们的实际的图像分类的类别。对于卷积层最后的图像我们只需要输出其是否属于一个特定的类。 输出层有一个像分类交叉熵那样的损失函数,来计算预测中的误差。一旦分类完成,反向传播就开始更新权重和偏差的错误和减少损失。

4、组合各个层

现在可以看到CNN由各种卷积层和池化层组成。 我们来看看网络是怎样的。
在这里插入图片描述

  • 我们将输入图像传递给第一个卷积层。 卷积输出作为激活图获得。卷积过滤器应用于层,从输入图像中提取相关特征进一步通过。
  • 每个过滤器应提供不同的功能,以帮助正确的类别预测。 如果我们需要保留图像的大小,我们使用相同的填充(零填充),使用其他明智的有效填充,因为它有助于减少特征的数量。
  • 然后添加池图层以进一步减少参数数量。
  • 在进行预测之前添加几个卷积和池化层。 卷积层有助于提取特征。 随着我们深入网络,提取更多特定的特征,而浅层网络则提取的特征更为通用。
  • 如前所述,CNN中的输出层是全连接层,其中来自其他层的输入被平坦化并发送,以便将输出转换为网络所需的类的数量。
  • 输出然后通过输出层生成,并与输出层进行比较以生成错误。 在全连接的输出层中定义损失函数以计算均方损失。然后计算误差的梯度。
  • 然后错误被反向传播以更新过滤器(权重)和偏差值。
  • 一次训练周期在一次前进和后退过程中完成。
5、使用卷积神经网络对图片进行分类

让我们尝试一个例子,我们输入几个猫和狗的图像,我们尝试将这些图像分类到它们各自的动物类别中。 这是图像识别和分类的经典问题。 该机器需要做的是看到图像,并通过各种功能了解其是猫还是狗。

这些特征可以像提取边缘,或提取猫的胡须等。卷积层将提取这些特征,让我们一起来看看数据集。

这些是数据集中某些图像的示例。
在这里插入图片描述
我们首先需要调整这些图像的大小以使它们全部处于相同的形状。 这是我们在处理图像时通常需要做的事情,因为在捕获图像时,不可能捕获所有尺寸相同的图像。

为了简化理解,我只使用了一个单个卷积层和单个池化层,当我们尝试进行预测时,而通常我们是不会定义这种简单的神经网络结构的。

#导入各种库文件

import os
import numpy as np
import pandas as pd
import scipy
import sklearn
import keras
from keras.models import Sequential
import cv2
from skimage import io
%matplotlib inline
#定义文件路径
cat=os.listdir("/mnt/hdd/datasets/dogs_cats/train/cat")
dog=os.listdir("/mnt/hdd/datasets/dogs_cats/train/dog")
filepath="/mnt/hdd/datasets/dogs_cats/train/cat/"
filepath2="/mnt/hdd/datasets/dogs_cats/train/dog/"
#载入图片
images=[]
label = []
for i in cat:
image = scipy.misc.imread(filepath+i)
images.append(image)
label.append(0) #for cat images

for i in dog:
image = scipy.misc.imread(filepath2+i)
images.append(image)
label.append(1) #for dog images<br>
#调整所有图像的大小
for i in range(0,23000):
images[i]=cv2.resize(images[i],(300,300))

#将图像转换为数组
images=np.array(images)
label=np.array(label)

# 定义超参数
filters=10
filtersize=(5,5)

epochs =5
batchsize=128

input_shape=(300,300,3)

#将目标变量转换为所需的大小
from keras.utils.np_utils import to_categorical
label = to_categorical(label)
#定义模型
model = Sequential()

model.add(keras.layers.InputLayer(input_shape=input_shape))

model.add(keras.layers.convolutional.Conv2D(filters, filtersize, strides=(1, 1), padding='valid', data_format="channels_last", activation='relu'))
model.add(keras.layers.MaxPooling2D(pool_size=(2, 2)))
model.add(keras.layers.Flatten())

model.add(keras.layers.Dense(units=2, input_dim=50,activation='softmax'))

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(images, label, epochs=epochs, batch_size=batchsize,validation_split=0.3)

model.summary()

在这里插入图片描述
在这个模型中,我只使用了一个卷积和池化层,可训练参数是219801。 通过添加更多的卷积和图层,可以进一步减少参数的数量,我们添加提取的特征的卷积层会更具体和复杂。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值