神经网络优化(五) - 卷积网络基础
本节目标:学会使用 CNN 实现对手写数字的识别
上几节重点讲述的 NN :每个神经元与前后相邻层的每一个神经元都有连接关系,输入是特征,输出为预测的结果
参数个数:∑ (前层× 后层+ 后层)
从上面可以看出,一张分辨率仅为28*28像素的黑白图像,在神经网络运算时就有近40万个参数待优化;而现实生活中高分辨率的彩色图像,不但像素点增多,而且有红绿蓝三通道信息,这样直接喂入(全连接)神经网络时,待优化参数将无限增大。
待优化参数的增多,容易导致模型的过拟合,为了避免该现象,在实际应用中一般不会将原始图片直接未入全连接网络。
实际操作方案:先对原始图像进行特征提取,然后将特征喂入全连接网络,之后再然全连接网络计算分类评估值。
1 卷积计算
1.1 无padding的卷积计算
卷积(也称为滤波器)是一种有效提取图像特征的方法。
一般用一个正方形卷积核,遍历图像上的每一个点。图像区域内的每一个像素值乘以卷积核内相对应点的权重,求和,再加上偏置。
输出图像值边长 = (输入图像边长 - 卷积核长 + 1 )/ 步长
备注:
5*5*1的灰度图释义为 5 行 5 列的灰度值:1表示单通道,5*5表示分辨率,在矩阵中意味 5 行 5 列。
3*3*1的卷积核对灰度图进行卷积计算,对应值乘积求和,再加上偏置项 b = 1 ;让卷积核中的 [1, 1] 值遍历 5*5 中的每一个灰度值 。
输出图片边长: ( 输入图像边长 5 - 卷积核边长 3 + 偏置项 1 )/ 步长 1 = 3
由于仅用了一个3*3*1卷积核,所以输出的深度是1
1.2 含padding的卷积计算
不含padding的卷积计算图像矩阵长度会不一致;有时为了让图像的输出、输出尺寸一致,会再输入图像像素值周边补充0。
在前面 5x5x1 的图片周围进行全零填充,可使输出图片仍保持 5x5x1 的维度。这个全零填充的过程叫做 padding。
输出数据体的长度为:
( W − F + 2P ) / S + 1
- W:输入数据体尺寸
- F:卷积层中神经元感知域
- S:步长
- P:零填充的数量。
在 Tensorflow 框架中,用参数 padding = ‘ SAME ’(全部 0 填充) 或 padding = ‘VALID ’(不用 0 填充) 表示 。
两者的结果若非整数,都是采用 “ 向上取整 ” 的方式获得最终值。
示例:
输入图像为32*32*3,卷积核为5*5*3。
不用 0 填充时,输出(32 - 5 + 1)/ 1 = 28
若让输出结果长度与输入的一致,则需要填充几层 0 ?
32 = ( 32 - 5 + 2P) / 1 + 1,计算得 P = 2,故需要填充 2 层零。
2 Tensorflow中的卷积计算(单通道)
tensorflow 中计算卷积的函数为 tf.nn.conv2d()
tf.nn.conv2d(输入描述 卷积核描述核滑动步长padding)
注解:
1)输入描述
[ batch, 5 , 5, 1 ]
- batch - 一次喂入图片数量
- 5, 5 - 两个数组一同描述每张图片的分辨率,5行5列
- 1 - 图片的通道数,若为灰度图,则为1,若为RGB的彩色,则为3
2)卷积核描述
[ 3, 3, 1, 16 ]
- 3, 3 - 卷积核的行列分辨率(3行3列)
- 1 - 通道数,卷积核的通道数是由输入图片的通道数决定的,其必须与输入图片的通道数一致
- 16 - 该卷积核数量为16个,共计进行16次卷积运算,则输入图片的深度为16,也就是说输出是16通道
3)核滑动步长
[ 1, 1, 1, 1 ]
- 第一个 1 - 固定的数值
- 第二个 1 - 行步长
- 第三个 1 - 列步长
- 第四个 1 - 固定的数值
4)padding
该处以字符串形式给出,例如本处 “ VALID “ 表示不用 零 来填充。
3 Tensorflow中的卷积计算(多通道)
上面是对单通道的灰度图进行阐述,而实际多是RGB三个颜色组成彩色图片,这也意味这图片对应有三个通道,每一种颜色对应一个通道。
由上面的规则可知,卷积核的深度 = 输入图片的通道数,所以卷积核也必须有 3 个通道。如下图所示
注解:
1)输入图片为RGB彩色图片,将其在R、G、B 的三色建立分量数据,5*5*3 即为每个分量为 5*5,3个通道。
2)卷积核也建立 3*3 个数据,为了匹配和输入数据通道,也建立 3 个通道的卷积核。
3)多通道与单通道的计算方法相似,每一个通道对应乘积和,再将每个通道和相加,最后加上偏置项 b = 1 ,最后得到一个输出值。
4)将滑动卷积核逐一求算出输出值,由于一共用了16个卷积核,所以最后输出图片是 5*5*16。
在Tensorflow中的代码形式与单通道一致,仅将通道数值进行修改即可,具体如下:
4 池化 Pooling
池化的目的减少特征数据量,但是不改变图片的深度,因为尽管经过卷积核计算,但是数据量还是非常大的。
Tensorflow 给出了计算池化的函数
- 最大池化 tf.nn.max_pool 函数,提取图片纹理。
- 平均池化 tf.nn.avg_pool 函数,保留背景特征。
函数的实际应用:
备注:
- 1)对输入的描述:给出一次输入 batch 张图片、行列分辨率、输入通道的个数。
- 2)对池化核的描述:只描述行分辨率和列分辨率,第一个和最后一个参数固定是 1。
- 3)对池化核滑动步长的描述:只描述横向滑动步长和纵向滑动步长,第一个和最后一个参数固定是 1。
- 4)是否使用 padding:padding 可以是使用零填充 SAME 或者不使用零填充VALID。
5 舍弃 dropout
在全连接神经网络训练过程中,为了减少过多参数,常使用舍弃dropout的方法。该方法可以有效防止过拟合。
实际上dropout时,是随机将神经元中的某些值置为 0 ,使其不参与参数优化。
将一部分神将元按照一定概率从神经网络中暂时舍弃,在使用神经网络时,会把所有的神经元恢复到神经网络中。
如下图,右图中带有 × 号标记的圆圈表示 dropout 掉的,
在 tensorflow 中的计算方法为
tf.nn.dropout(上层输出,暂时舍弃的概率)
在实际应用中,常在前向传播过程构建神经网络中使用dropout,减少过拟合、加快模型的训练速度。
if train: 输出 = tf.nn.dropout(上层输出,暂时舍弃的概率)
6 CNN 模块
卷积NN :借助卷积核(Kernel)提取特征后,送入全连接网络。
卷积神经网络可分为两部分:
- 首先是通过卷积、激活、池化对输入图片特征进行提取主要特征信息
- 再次将提取的特征信息喂入全连接网络中
卷积神经网络从诞生到现在,已经出现了许多经典网络结构,比如 Lenet-5、Alenet、VGGNet、GoogleNet 和 ResNet 等。每一种网络结构都是以卷积、激活、池化、全连接这四种操作为基础进行扩展。
Lenet-5 是最早出现的卷积神经网络,由 Lecun 团队首先提出,Lenet-5 有效解决了手写数字的识别问题。
7 lenet-5 代码讲解
该代码来源于文章:
Y. LeCun, L. Bottou, Y. Bengio, and P. Haffner. Grandient-based learning applied to document recognition. Proceedings of the IEEE, 86(11):2278-2324, 1998.
该篇文章的代码如下所示。
依据上述代码是依据文章中梳理出来的,而mnist数据集训练是28*28,其计算过程如下:
7.1 前向传播过程 mnist_lenet5_forward
# coding:utf-8 import tensorflow as tf # 每个图片的像素点为28 IMAGE_SIZE = 28 # 由于是灰度图,每个图片的通道为1 NUM_CHANNELS = 1 # 第一层卷积核的大小为5 CONV1_SIZE = 5 # 第一层使用了32个卷积核 CONV1_KERNEL_NUM = 32 # 第二层卷积核大小为5 CONV2_SIZE = 5 # 第二层使用了64个卷积核 CONV2_KERNEL_NUM = 64 # 第一层神经网络有512个神经元 FC_SIZE = 512 # 第二层神经网络有10个神经元 OUTPUT_NODE = 10# 权重w的生成函数, # shape表示生成张量的维度 # regularizer表示正则化权重 def get_weight(shape, regularizer):w = tf.Variable(tf.truncated_normal(shape, stddev=0.1))if regularizer != None: tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(regularizer)(w)) return w# 偏置b生成函数 def get_bias(shape):b = tf.Variable(tf.zeros(shape)) return b# 卷积生成函数 def conv2d(x, w):# x输入图片描述[batch, 行分辨率,列分辨率,通道数]# w卷积核描述[行分辨率,列分辨率,通道数,卷积核个数]# strides 核滑动步长[1,行步长,列步长,1]# padding 填充模式 SAME零填充return tf.nn.conv2d(x, w, strides=[1, 1, 1, 1], padding='SAME')# 最大池化计算函数 def max_pool_2x2(x):# x 输入描述[batch,行分辨率,列分辨率,通道数]# ksize 池化核描述[1,行分辨率,列分辨率,1]# strides 池化核滑动步长[1,行步长,列步长,1]# padding 填充模式return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') # 前向传播的网络结构 def forward(x, train, regularizer):# 第一层卷积核conv1_w = get_weight([CONV1_SIZE, CONV1_SIZE, NUM_CHANNELS, CONV1_KERNEL_NUM], regularizer) # 初始化第一层偏置项bconv1_b = get_bias([CONV1_KERNEL_NUM]) # 执行卷积计算conv1 = conv2d(x, conv1_w) # 对conv1添加偏置,并通过relu激活函数进行激活输出relu1 = tf.nn.relu(tf.nn.bias_add(conv1, conv1_b)) # 最大池化,第一层最终输出pool1pool1 = max_pool_2x2(relu1) # 第二层卷积核的深度CONV1_KERNEL_NUM等于上层卷积核的个数conv2_w = get_weight([CONV2_SIZE, CONV2_SIZE, CONV1_KERNEL_NUM, CONV2_KERNEL_NUM],regularizer) conv2_b = get_bias([CONV2_KERNEL_NUM])# 第二层卷积核的输入是第一层的输出conv2 = conv2d(pool1, conv2_w) relu2 = tf.nn.relu(tf.nn.bias_add(conv2, conv2_b))# pool2是第二层的最后输出pool2 = max_pool_2x2(relu2)# 将pool2从三维张量变成二维张量# 获得pool2的数据维度,并存入list中pool_shape = pool2.get_shape().as_list() # pool_shape[0] 的值是一个batch值# pool_shape[1] 特征的长度# pool_shape[2] 特征的宽度# pool_shape[3] 特征的深度# nodes=长度*宽度*深度,所有数据点的个数nodes = pool_shape[1] * pool_shape[2] * pool_shape[3] # 将pool2表示成以batch作为行,所有特征点为列的二维形状,# 把reshaped 喂入全连接网络中reshaped = tf.reshape(pool2, [pool_shape[0], nodes]) fc1_w = get_weight([nodes, FC_SIZE], regularizer) fc1_b = get_bias([FC_SIZE]) # 把上层的输出reshaped 乘以 本层线上的权重fc1_w,再加上偏置fc1_bfc1 = tf.nn.relu(tf.matmul(reshaped, fc1_w) + fc1_b) # 如果是训练阶段,则对fc1的50%进行dropoutif train: fc1 = tf.nn.dropout(fc1, 0.5)# 通过第二层全连接网络,初始化第二层W和bfc2_w = get_weight([FC_SIZE, OUTPUT_NODE], regularizer)fc2_b = get_bias([OUTPUT_NODE])# 上层的输出fc1和本层fc2_w相乘,再加上fc2_by = tf.matmul(fc1, fc2_w) + fc2_breturn y
7.2 反向传播过程 mnist_lenet5_backward
#coding:utf-8 import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data import mnist_lenet5_forward import os import numpy as npBATCH_SIZE = 100 LEARNING_RATE_BASE = 0.005 LEARNING_RATE_DECAY = 0.99 REGULARIZER = 0.0001 STEPS = 50000 MOVING_AVERAGE_DECAY = 0.99 MODEL_SAVE_PATH="./model/" MODEL_NAME="mnist_model" def backward(mnist):x = tf.placeholder(tf.float32,[# 每轮喂入的图片数量 BATCH_SIZE,# 行分辨率 mnist_lenet5_forward.IMAGE_SIZE,# 列分辨率 mnist_lenet5_forward.IMAGE_SIZE,# 输入的通道数 mnist_lenet5_forward.NUM_CHANNELS]) y_ = tf.placeholder(tf.float32, [None, mnist_lenet5_forward.OUTPUT_NODE])# True 意味使用dropout操作y = mnist_lenet5_forward.forward(x,True, REGULARIZER) global_step = tf.Variable(0, trainable=False) ce = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))cem = tf.reduce_mean(ce) loss = cem + tf.add_n(tf.get_collection('losses')) learning_rate = tf.train.exponential_decay( LEARNING_RATE_BASE,global_step,mnist.train.num_examples / BATCH_SIZE, LEARNING_RATE_DECAY,staircase=True) train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)ema_op = ema.apply(tf.trainable_variables())with tf.control_dependencies([train_step, ema_op]): train_op = tf.no_op(name='train')saver = tf.train.Saver() with tf.Session() as sess: init_op = tf.global_variables_initializer() sess.run(init_op) ckpt = tf.train.get_checkpoint_state(MODEL_SAVE_PATH) if ckpt and ckpt.model_checkpoint_path:saver.restore(sess, ckpt.model_checkpoint_path) for i in range(STEPS):xs, ys = mnist.train.next_batch(BATCH_SIZE) reshaped_xs = np.reshape(xs,( BATCH_SIZE,mnist_lenet5_forward.IMAGE_SIZE,mnist_lenet5_forward.IMAGE_SIZE,mnist_lenet5_forward.NUM_CHANNELS))_, loss_value, step = sess.run([train_op, loss, global_step], feed_dict={x: reshaped_xs, y_: ys}) if i % 100 == 0: print("After %d training step(s), loss on training batch is %g." % (step, loss_value))saver.save(sess, os.path.join(MODEL_SAVE_PATH, MODEL_NAME), global_step=global_step)def main():mnist = input_data.read_data_sets("./data/", one_hot=True) backward(mnist)if __name__ == '__main__':main()
7.3 测试 mnist_lenet5_test
#coding:utf-8 import time import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data import mnist_lenet5_forward import mnist_lenet5_backward import numpy as npTEST_INTERVAL_SECS = 5def test(mnist):with tf.Graph().as_default() as g: x = tf.placeholder(tf.float32,[mnist.test.num_examples,mnist_lenet5_forward.IMAGE_SIZE,mnist_lenet5_forward.IMAGE_SIZE,mnist_lenet5_forward.NUM_CHANNELS]) y_ = tf.placeholder(tf.float32, [None, mnist_lenet5_forward.OUTPUT_NODE])y = mnist_lenet5_forward.forward(x,False,None)ema = tf.train.ExponentialMovingAverage(mnist_lenet5_backward.MOVING_AVERAGE_DECAY)ema_restore = ema.variables_to_restore()saver = tf.train.Saver(ema_restore)correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) while True:with tf.Session() as sess:ckpt = tf.train.get_checkpoint_state(mnist_lenet5_backward.MODEL_SAVE_PATH)if ckpt and ckpt.model_checkpoint_path:saver.restore(sess, ckpt.model_checkpoint_path)global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1] reshaped_x = np.reshape(mnist.test.images,(mnist.test.num_examples,mnist_lenet5_forward.IMAGE_SIZE,mnist_lenet5_forward.IMAGE_SIZE,mnist_lenet5_forward.NUM_CHANNELS))accuracy_score = sess.run(accuracy, feed_dict={x:reshaped_x,y_:mnist.test.labels}) print("After %s training step(s), test accuracy = %g" % (global_step, accuracy_score))else:print('No checkpoint file found')returntime.sleep(TEST_INTERVAL_SECS) def main():mnist = input_data.read_data_sets("./data/", one_hot=True)test(mnist)if __name__ == '__main__':main()
神经网络优化(五) - 卷积网络基础相关推荐
- Interview:算法岗位面试—10.24下午—上海某软件公司(机器学习,上市)电话面试—考察SVM、逻辑回归、降低过拟合、卷积网络基础等
Interview:算法岗位面试-10.24下午-上海某软件公司(机器学习,上市)电话面试-考察SVM.逻辑回归.降低过拟合.卷积网络基础等 导读:当时电话来的非常快,我刚做完一家公司的笔试,接着来了 ...
- PaddlePaddle训练营——公开课——AI核心技术掌握——第2章机器能“看”的现代技术——源自视觉神经原理的卷积网络简介及深入理解
源自视觉神经原理的卷积神经网络简介 基于人们对于生物视觉的研究,科学家们给出了在计算机视觉中的具备良好表现的卷积神经网络模型. 卷积神经网络发展概况 1.在这个结构中可以使用反向传播来训练权重. 2. ...
- 卷积网络基础知识---Group Convolution分组卷积
Group Convolution分组卷积,以及Depthwise Convolution和Global Depthwise Convolution https://www.cnblogs.com/s ...
- 卷积网络基础知识---Depthwise Convolution Pointwise Convolution Separable Convolution
https://yinguobing.com/separable-convolution/#fn2 卷积神经网络在图像处理中的地位已然毋庸置疑.卷积运算具备强大的特征提取能力.相比全连接又消耗更少的参 ...
- 学习笔记CB009:人工神经网络模型、手写数字识别、多层卷积网络、词向量、word2vec...
人工神经网络,借鉴生物神经网络工作原理数学模型. 由n个输入特征得出与输入特征几乎相同的n个结果,训练隐藏层得到意想不到信息.信息检索领域,模型训练合理排序模型,输入特征,文档质量.文档点击历史.文档 ...
- 通信网络基础期末复习-第五章-路由算法
写在前面:本文主要依据为<通信网络基础>李建东,盛敏编著,如有侵权,请联系作者删除.本文仅用于个人期末复习与知识结构的搭建. 文章目录 第五章 路由算法 5.1 路由算法概述 5.1.1路 ...
- 4.4)深度卷积网络:人脸识别和神经风格转换
目录 1)What is face recognition? 2)One-shot learning 3)Siamese network 4)Triplet Loss(重点) 5)Face Verif ...
- 第五章 网络 之 计算机网络基础(一)
文章目录 (一)计算机网络基础知识:从一次完整的网络请求过程分析 (1)域名解析 1.1)域名与ip地址 1.2)域名系统(DNS--Domain Name System) a)DNS本质 b)域名的 ...
- 20145209刘一阳《网络对抗》实验五:MSF基础应用
20145209刘一阳<网络对抗>实验五:MSF基础应用 主动攻击 首先,我们需要弄一个xp sp3 English系统的虚拟机,然后本次主动攻击就在我们kali和xp之间来完成. 然后我 ...
最新文章
- MIT新研究给量子计算机「泼冷水」:自然界辐射会干扰它,需要研究新对策 | Nature...
- VS调试python中的DLL
- tableau可视化数据分析60讲(一)-tableau概念性叙述及环境配置
- 【Python基础】Python安装第三方库太慢?配置好这个速度飞起
- boost::math::fisher_f用法的测试程序
- c# uri.host_C#| Uri.FromHex()方法与示例
- 套接字I/O模型-重叠I/O
- spring cloud gateway Unhandled failure: Only one connection receive subscriber allowed.
- PMP更新教材了,怎么备考?
- android数码管字体,matplotlib绘图时显示额外的“figure”浮窗
- 2008年(第五版)北大中文核心期刊目录
- python聊天室socket+tkinter_基于socket和tkinter的python网络聊天室程序
- 中国云计算的十年江湖
- The Auto-extending innodb_system data file './ibdata1' is of a different size 6400 pages (rounded do
- C函数参数中的三个点
- 用python绘制玫瑰花
- python绘制樱花洒落_Python:绘制樱花树
- django.db.utils.OperationalError: (2003, Can't connect to MySQL server on ‘127.0.0.1’)
- Could not transfer artifact 报错解决
- [NLP]预处理--使用re正则化进行文本清理
热门文章
- oracle standby同步,PRIMARY Standby不能同步问题
- java快速注释怎么配置_详解如何在低版本的Spring中快速实现类似自动配置的功能...
- assimp android build,使用Android Studio+CMakeLists编译assimp
- ssh传输越多越慢_Linux下分析网站访问慢原因
- python做动画的库_用matplotlib动画库制作等分法动画
- php 筛选搜索,筛选——搜索
- pytorch GPU
- sqlalchemy 聚合
- D3 interpolate
- Python __add__