卷积神经网络基本结构介绍以及代码实现

1、基本结构

在这里插入图片描述

从左往右依次是两次卷积加池化,加三次全连接。

2、卷积

卷积层,听名字就可以知道是卷积神经网络中最主要的一层。它的作用

就是用一个局部区域去扫描整个图片,我把它理解成类似于在图片上打了一个马赛克,相当于把图片的像素减少,

把相邻的几个像素用一个像素表示,不过当然不是随意的表示,而是这几个相邻的像素分别有不同的权重,而且对于每个卷积后的像素来说,还有一个阈值来确保这个卷积后的像素可以更好的代表卷积前相邻像素的一个集合。可以理解为保持图像识别度不变的马赛克操作。
在这里插入图片描述

像上图的操作,用一个四个像素的卷积核,一次扫描整个图片像素。

2.1局部连接与权值共享

在这里插入图片描述

局部连接和全连接顾名思义,就如上图所示。

对于全连接来说,每个下层元素都要有对上层每个元素的权值,而局部连接只需要其中一部分元素的权值就可以了。

什么叫权值共享呢,意思就是对于局部连接来说,如上图所示,每个下层元素对于上层元素有三个不同的权值,而每个下层元素的权值都是相同的三个,就叫权值共享。

这里你可能会问,权值都一样难道不会影响计算结果吗?这就要涉及神经网络算法巧妙之处了,我可以先肯定的告诉你,不会的,反而会使计算结果更加精确,还能加快运算和减少存储空间。

2.2卷积过程演示

定义一个filter就是一个卷积核。用于扫描图片。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YhpNWgx4-1618814882681)(E:\python学习\CNN网络结构的学习与实现\卷积神经网络CNN.assets\image-20210419130352273.png)]

对应每个位置的权值。现在拿它去扫描图片。
在这里插入图片描述

得到一个卷积后的结果。

3、池化

池化操作就是对接受到的卷积后的结果再继续进一步的特征提取。比如说将相邻几个像素,只保留其最大值。

在这里插入图片描述

这里定义了一个2*2的filter,移动步长为2,即每次移动两个像素。池化操作主要目的就是减小细节,简化计算。

3.1 非线性映射ReLU

这其实也是一种特征提取的过程。对于上一次卷积的到后的结果通过这个函数先进行一步数据处理。
在这里插入图片描述

这个函数可以理解为,负数是非主要信息,过滤,保留正数为有效信息。由这个函数处理完之后的数据再交由池化层进行池化操作。

3.2 二次卷积和池化

在这里插入图片描述

前面的四层为两次卷积和池化,所以第三第四层的处理和之前一样,这四层处理完之后就可以说是将这个图片的特征信息都提取出来了。

4、全连接

就是上面提到的操作。

在这里插入图片描述

由于现在得到的是图片的特征信息了,所以可以进行较为复杂的运算操作来确保模型的准确性。

第五、六、七层都是全连接层。

5、多filter卷积

你可能对之前的网络结构有疑惑。
在这里插入图片描述

为什么在进行一次卷积之后或出现六个面?这是因为一次卷积可以有多个filter,因为卷积其实就是通过权值来提取特征信息,那么一个filter显然是不够的,一个filter可以理解为提取一类特征信息,比如说第一个filter是提取图像整体轮廓的,而第二个filter是提取特征颜色的,第三个是提取对比度的等等等。

而从卷积到池化只是面积变小了这点其实好理解。就是打了一个保留特征的马赛克。

从第三层到第四层,可以看到6个面变为16个面,这里刚开始我也是很难理解的,我以为如果有两个filter那么第四层应该是6×2个面,也就是第四层的面数应该为第三层的整数倍才对。后来才明白,这里的16和前面的6完全没有关系,之所以有16个面是因为第四层有16个filter,那么为什么不是6×16呢?

因为一个filter不一定是一个面它可能是多维的,在这里可以理解为每个filter都是三维的。

在这里插入图片描述

而它的深度为6,即将6个面叠在一起进行卷积操作。

filter的现状类似下图:

在这里插入图片描述

6层卷积后得到一个面

6、卷积操作函数实现

6.1 卷积操作参数说明

这里需要用到python的TensorFlow库,这个库里面提供了现成的卷积和池化函数。

tensorflow.nn.conv2d #卷积函数
tensorflow.nn.max_pool #池化函数

这里用到了TensorFlow,如果这里有疑问的话,可以看看这篇文章:TensorFlow零基础入门,实现手写数字识别.
先来看一下这两个函数的参数

def conv2d(input, filter, strides, padding, use_cudnn_on_gpu=True, data_format="NHWC", dilations=[1, 1, 1, 1], name=None):

这个卷积函数的参数我们只需要关注前面四个。

input:表示输入的图片,这里的图片是一个四维的数组形式,Given an input tensor of shape [batch, in_height, in_width, in_channels]四个维度分别是,图片数量,宽度,高度和通道数,这里的通道数指的是图片的颜色通道,比如rgb就是三个通道。

filter:表示输入的卷积核,也是一个四维数组形式,filter tensor of shape [filter_height, filter_width, in_channels, out_channels],四个维度表示卷积核的宽,高,深度和个数

strides:卷积核移动的步长也是一个数组[1 , step, step, 1]第一和第四个参数固定为1,中间两个参数表示水平移动步长和垂直移动步长。

padding:指的是填充,比如你的图片尺寸为5×5,而卷积核为2×2,那么移动的时候如果步长为2的话,就不能扫描完整张图片。所以需要对图片进行填充,一般选择0填充,参数就是padding='SAME'

def max_pool(value, ksize, strides, padding, data_format="NHWC", name=None):

这是池化函数,也只需要关注前面四个参数。

value:就是卷积后的结果

ksize:是一个数组 [1 , size, size, 1]第一和第四个参数固定为1,中间两个参数表示filter尺寸

strides和padding:和卷积函数一致

6.2 代码实现

import tensorflow as tf
import cv2
import numpy as np

img = cv2.imread('1.png')    # 图片读取
img = cv2.resize(img, (64, 64))/255   # 图片尺寸压缩和归一化
img_new = np.float32(np.reshape(img, [1, 64, 64, 3]))   # 将图片shape改为4维,由于conv2d函数读取的为32位浮点数,所以这里强转一下
w1 = tf.random_normal([3, 3, 3, 32])  # filter

conv1 = tf.nn.conv2d(img_new, w1, strides=[1, 1, 1, 1], padding='SAME')  # 卷积操作
pool1 = tf.nn.max_pool(conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')  # 进行池化操作

sess = tf.Session()   #打开会话
conv = sess.run(conv1)
pool = sess.run(pool1)
sess.close()          #关闭会话

cv2.imwrite('conv.jpg', conv[0, :, :, 15]*500)   # 将卷积结果的某一个面可视化呈现
cv2.imwrite('pool.jpg', pool[0, :, :, 15]*100)   # 将池化结果的某一个面可视化呈现
  • 20
    点赞
  • 94
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值