神经网络学习(三)比较详细 卷积神经网络原理、手写字体识别(卷积网络实现)
之前写了一篇基于minist数据集(手写数字0-9)的全连接层神经网络,识别率(85%)并不高,这段时间学习了一些卷积神经网络的知识又实践了一把, 识别率(96%左右)确实上来了 ,下面把我的学习过程记录下来以便加深理解也希望可以帮到大家伙儿。
一、准备工作
定义定义两个函数weight_variables(shape)、 bias_variables(shape)用来初始化权重偏置
# 定一个初始化权重的函数
def weight_variables(shape):"""初始化权重的函数:param shape::return:"""w = tf.Variable(tf.random_normal(shape=shape, mean=0.0, stddev=1.0))return w
# 定义一个初始化偏置的函数
def bias_variables(shape):"""初始化偏置的函数:param shape::return:"""b = tf.Variable(tf.constant(0.0, shape=shape))return b
二、自定义卷积模型
1. 老规矩先把位置占下
占位符这里就不赘述了、不明白的可以看上篇。
x = tf.placeholder(tf.float32, [None, 784])y_true = tf.placeholder(tf.float32, [None, 10])
2. 确定第一卷积层Filter_1的数量跟形状
Filter是什么 是干啥的 下面我会在卷积层通过图片1详细说。
这里我指定Filter_1的形状为5×5×1×32,即长=5、 宽=5、 高=1、 个数=32。
ps:看到这部分人会有疑问,为什么Filter_1的形状是5×5×1×32?其实可以指定Filter_1的形状为任意形状,只要其长宽不超过数据集中图片的长跟宽。当然不要太小也别太大,不然训练效果就不好了。其实Filter的形状是卷积模型中可调整的参数之一,其形状直接影响训练效果。
3. 根据Filter形状确定第一卷积层的权重跟偏置
Filter_1的形状有了那么权重跟偏置的形状就确定下来了,我们直接调用上文写的初始化函数。
# 初始化权重(这里要清楚 权重是跟Filter的形状挂钩的,Filter的形状是什么偏置的形状就是什么)w_conv1 = weight_variables([5, 5, 1, 32]) # 5行5列、1个通道、32个Filter# 初始化偏置(有几个Filter就有几个偏置bias)b_conv1 = bias_variables([32])
4.数据集的形状改变一下
[None,784]单位为张 即None张图片,一张图片的格式为28×28×1。
-1 在tensorflow中代表任意数或不确定数量。
# 对x(数据集)进行形状的改变。[None,784]=>[None,28,28,1]x_reshape = tf.reshape(x, [-1, 28, 28, 1])
5. 卷积层(convolution)(第一层)
图一动图中四列分别为:
1、第一列三张表格代表一张彩色图的三个通道(RGB)
2、第二列为一个Filter
3、第三列为另一个Filter
4、第四列为卷积结果
对Filter的理解:
1、可以把Filter看作 过滤网,此过滤网可以有好几层,其层数由数据集中图片的通道数决定。如图1 由第一列可以看到此图片有三个通道,那么第二三列Filter(过滤网)的层数均为3层。
2、一个卷积网络会有多个卷积层,每一卷积层都对应若干个Filter,我们这把这个若干个Filter称作Filter组或是“滤芯”。其实Filter的形状是卷积模型中可调整的参数之一,其形状直接影响训练效果。
3、如图1 每个Filter都有自己的偏置bias,第一个Filter的偏置为1,第二个Filter的偏置为0.
卷积操作流程:
1、用Filter去扫描图像矩阵(图1第一列),这个扫描过程就是将Filter矩阵与扫描区域矩阵对应位置相乘然后相加。后再加上Filter对应的偏置bias,最后按行跟列排列,得到卷积的输出(如图中第四列)此过程即为卷积。
2、老规矩 在这还要给神经网络添加非线性功能,也就是添加激活函数。现在深度学习中用到的激活函数99%都是用ReLU。也就是将图1中第四列的值传到ReLU函数中作为ReLU函数的输入。至此卷积层搞定。
3、代码中的参数解析:①x_reshape:训练数据占位符,可以认为它就是我们输入的图片数据(x),因为在训练的过程中我们会把图像数据往这里面放。
②w_conv1:权重(w),我们可以认为这权重就是Filter。所以w的形状跟Filter的形状是一样的。
③strides:滑动步长,Filter在扫描图片矩阵的时候,其左右上下的滑动间隔。tensorflow里面要求strides的形状为1×4,其实在strides=[1, 1, 1, 1]这个数组中只有中间两个数值有用,第一个跟第四个数值都是默认的1。绝大部分Filter的滑动步长(strides)都是1。
④padding:填充标志,看到这里不知道小伙伴们有没有发现一个问题,图1中Filter的滑动步长为2,正好在横向扫描的时候扫描三次,若滑动步长为3,当Filter扫描两次后 我们发现后面还剩1列无法扫描(因为Filter大小为3×3,扫描两次后 图像矩阵中剩余未扫描的部分为3×1)。这时候我们有两种选择:一 剩余的一列我不要了(padding=”VALID“),二 在整个图像矩阵外面在添加两圈零(padding=“SAME”),来补充图像矩阵。
4、图中图像数据非常少,所以卷积后期输出矩阵的形状(行跟列的数量)都很好算,当图像数据非常大时 比如当图像矩阵为1920×1080时 通过人眼是看不出卷积操作后输出矩阵(图1第四行)的形状的。这里给出公式:
其中W、H为元图像矩阵的行跟列,F为Filter的大小(比如一个3×3的Filter,其大小为3),P为Padding的值(即当在图像矩阵外圈添加一圈零)p需要手动计算:比如数据宽为28 Filter宽为5,28除5取余为3(当取余数为0时 p=0),p=5-3=2,也就是在补充2列0。(28-5+2*2)/1 +1 = 28,所以卷积后的输出为[None,28,28,32],其中32 为输出矩阵数量。
width跟height为卷积操作后输出矩阵的列数跟行数
# 卷积操作:[None,28,28,1]=>[None,28,28,32]
x_relu1 = tf.nn.relu(tf.nn.conv2d(x_reshape, w_conv1, strides=[1, 1, 1, 1], padding="SAME") + b_conv1)
图1
5. 池化层(Pooling)(第一层)
池化操作理解:
池化操作跟卷积操作非常相似但池化操作简单的多。一般池化操作分三种(Max Pooling、Mean Pooling、Random Pooling)其中最大值池化Max Pooling、均值池化Mean Pooling最常用。池化操作相对比较简单这里不多赘述,可以参考图2、图3,也可以参考文章。
# 池化操作(2*2、strides=1、个数=32),[None,28,28,32]=>[None,14,14,32]x_pool1 = tf.nn.max_pool(x_relu1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
图2
图3
6. 卷积层(convolution)(第二层)
原理与第一层卷积一样。其中Filter_2的 大小=5×5×64 , strides=1
#卷积层二 卷积:(filter_size=5*5*32、filter_number=64、strides=1) => 激活(tf.n.relu) => 池化2*2 strides=2# 随即初始化权重[5,5,32,64]w_conv2 = weight_variables([5, 5, 32, 64])# 随机初始化偏置b_conv2 = bias_variables([64])# 卷积([None,14,14,32]->[None,14,14,64])=>激活x_relu2 = tf.nn.relu(tf.nn.conv2d(x_pool1, filter=w_conv2, strides=[1, 1, 1, 1], padding="SAME") + b_conv2)
7. 池化层(Pooling)(第二层)
同池化层第一层,这里就不再叨叨了。
接下来流程: 全连接层=>优化(梯度下降)=>预测=>保存模型=>利用训练好的模型进行训练。这一系列流程在上篇已经详细介绍。
废话不多说直接上代码 ↓↓↓↓↓↓
三、源代码
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
from tensorflow.contrib.slim.python.slim.nets.inception_v3 import inception_v3_baseFlAGS = tf.flags.FLAGS
tf.flags.DEFINE_integer("is_train", 0, "指定程序是预测还是训练")def conv_fc():# 获取数据mnist = input_data.read_data_sets("./data/mnist/input_data/", one_hot=True)# 专门定义一个模型函数,得出输出x, y_true, y_predict, w_fc, b_fc = model()# 求所有样本的损失、然后求平均值with tf.variable_scope("soft_cross"):# 求平均交叉熵损失(先经过softmax得到概率,后交叉熵拿损失,后求平均损失)loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=y_predict))# 梯度下降优化损失with tf.variable_scope("optimizer"):train_op = tf.train.GradientDescentOptimizer(0.0001).minimize(loss)# 计算准确率with tf.variable_scope("acc"):# 分别拿到预测样本跟目标样本每一行的最大下标 ,若下表相等 返回1 不相等返回0equal_list = tf.equal(tf.argmax(y_true, 1), tf.argmax(y_predict, 1))# 准确率=算平均值 None个样本 [1,0,1,0,1,1,0,1,..............................]accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32))# 定一个初始化变量的opinit_op = tf.global_variables_initializer()# 收集变量 (一维)单个数字值收集tf.summary.scalar("losses", loss)tf.summary.scalar("acc", accuracy)# 收集变量 高纬度变量收集tf.summary.histogram("weightes", w_fc)tf.summary.histogram("biases", b_fc)# 定义一个合并变量的操作operationmerged = tf.summary.merge_all()# 定义一个saver用于保存模型saver = tf.train.Saver()correct = 0# 开启会话运行训练with tf.Session() as sess:filewriter = tf.summary.FileWriter("./temp/summary/test_conv/", graph=sess.graph)sess.run(init_op)if FlAGS.is_train == 1:# 循环进行训练for i in range(100000):# 取出真实存在的目标值和特征值mnist_x, mnist_y = mnist.train.next_batch(50)# 运行train_op训练sess.run(train_op, feed_dict={x: mnist_x, y_true: mnist_y})# 写入每一步训练的值summary = sess.run(merged, feed_dict={x: mnist_x, y_true: mnist_y})filewriter.add_summary(summary, i)print("训练地%d步,准确率为:%f" % (i, sess.run(accuracy, feed_dict={x: mnist_x, y_true: mnist_y})))# 保存模型saver.save(sess, "./temp/ckpt_conv/fc_model")else:saver.restore(sess, "./temp/ckpt_conv/fc_model")# 如果是0,则作出预测for i in range(100):# 每次测试一张图片x_test, y_test = mnist.test.next_batch(1)print("第%d张图片目标是%d,预测结果是:%d" % (i,tf.argmax(y_test, 1).eval(),tf.argmax(sess.run(y_predict, feed_dict={x: x_test, y_true: y_test}), 1).eval()))if (tf.argmax(y_test, 1).eval() == tf.argmax(sess.run(y_predict, feed_dict={x: x_test, y_true: y_test}),1).eval()):correct += 1print("100样本预测准确率:%f" % (correct / 100))return Nonedef model():"""自定义的ziding卷积模型:return:"""# 1、准备占位符 x [None,784] y_true[None,10]with tf.variable_scope("data"):x = tf.placeholder(tf.float32, [None, 784])y_true = tf.placeholder(tf.float32, [None, 10])# 2、卷积层一 卷积:(filter_size=5*5*1、filter_number=32、strides=1) => 激活(tf.n.relu) => 池化(2*2、strides=1、个数=32)with tf.variable_scope("conv1"):# 初始化权重(这里要清楚 权重是跟Filter的形状挂钩的,Filter的形状是什么偏置的形状就是什么)w_conv1 = weight_variables([5, 5, 1, 32]) # 5行5列、1个通道、32个Filter# 初始化偏置(有几个Filter就有几个偏置bias)b_conv1 = bias_variables([32])# 对x(数据集)进行形状的改变。[None,784]=>[None,28,28,1]x_reshape = tf.reshape(x, [-1, 28, 28, 1])# 卷积操作:[None,28,28,1]=>[None,28,28,32]x_relu1 = tf.nn.relu(tf.nn.conv2d(x_reshape, w_conv1, strides=[1, 1, 1, 1], padding="SAME") + b_conv1)# 池化操作(2*2、strides=1、个数=32),[None,28,28,32]=>[None,14,14,32]x_pool1 = tf.nn.max_pool(x_relu1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")# 3、卷积层二 卷积:(filter_size=5*5*32、filter_number=64、strides=1) => 激活(tf.n.relu) => 池化2*2 strides=2with tf.variable_scope("conv2"):# 随即初始化权重[5,5,32,64]w_conv2 = weight_variables([5, 5, 32, 64])# 随机初始化偏置b_conv2 = bias_variables([64])# 卷积([None,14,14,32]->[None,14,14,64])=>激活x_relu2 = tf.nn.relu(tf.nn.conv2d(x_pool1, filter=w_conv2, strides=[1, 1, 1, 1], padding="SAME") + b_conv2)# 池化操作2*2 strides=2,[None,14,14,64]=>[None,7,7,64]x_pool2 = tf.nn.max_pool(x_relu2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")# 4、全连接层[None,7,7,64]=>[None,7*7*64]*[7*7*64,10]+[10] = [None,10]with tf.variable_scope("conv2"):# 随机初始化权重和偏执w_fc = weight_variables([7 * 7 * 64, 10])b_fc = bias_variables([10])# 修改形状 x_pool2[None,7,7,64]=>[None,7*7*64]x_fc_reshape = tf.reshape(x_pool2, [-1, 7 * 7 * 64])# 进行矩阵预算得出每个样本的10个结果y_predict = tf.matmul(x_fc_reshape, w_fc) + b_fcreturn x, y_true, y_predict, w_fc, b_fc# 定一个初始化权重的函数
def weight_variables(shape):"""初始化权重的函数:param shape::return:"""w = tf.Variable(tf.random_normal(shape=shape, mean=0.0, stddev=1.0))return w# 定义一个初始化偏置的函数
def bias_variables(shape):"""初始化偏置的函数:param shape::return:"""b = tf.Variable(tf.constant(0.0, shape=shape))return bif __name__ == "__main__":conv_fc()
四、效果一览
1、我这边训练练了10W次 用时15分钟
2、训练时电脑的运行状态。
3、用了1000张图片测试模型的可靠程度。如下图 准确率为94.9%
神经网络学习(三)比较详细 卷积神经网络原理、手写字体识别(卷积网络实现)相关推荐
- 神经网络学习(二)Tensorflow-简单神经网络(全连接层神经网络)实现手写字体识别
神经网络学习(二)神经网络-手写字体识别 框架:Tensorflow 1.10.0 数据集:mnist数据集 策略:交叉熵损失 优化:梯度下降 五个模块:拿数据.搭网络.求损失.优化损失.算准确率 一 ...
- 《MATLAB 神经网络43个案例分析》:第19章 基于SVM的手写字体识别
<MATLAB 神经网络43个案例分析>:第19章 基于SVM的手写字体识别 1. 前言 2. MATLAB 仿真示例 3. 小结 1. 前言 <MATLAB 神经网络43个案例分析 ...
- 神经网络实现手写字体识别
神经网络入门学习中,进行了手写字体识别实践,该篇博客用于记录实践代码,以备后续使用. 关键词:神经网络,前向传播.反向传播.梯度下降.权值更新.手写字体识别 1. 实践代码 import numpy ...
- 基于Python神经网络的手写字体识别
本文将分享实现手写字体识别的神经网络实现,代码中有详细注释以及我自己的一些体会,希望能帮助到大家 (≧∇≦)/ ############################################ ...
- 深度学习笔记:01快速构建一个手写数字识别系统以及张量的概念
深度学习笔记:01快速构建一个手写数字识别系统 神经网络代码最好运行在GPU中,但是对于初学者来说运行在GPU上成本太高了,所以先运行在CPU中,就是慢一些. 一.安装keras框架 使用管理员模式打 ...
- python手写字体程序_深度学习---手写字体识别程序分析(python)
我想大部分程序员的第一个程序应该都是"hello world",在深度学习领域,这个"hello world"程序就是手写字体识别程序. 这次我们详细的分析下手 ...
- 深度学习,实现手写字体识别(大数据人工智能公司)
手写字体识别是指给定一系列的手写字体图片以及对应的标签,构建模型进行学习,目标是对于一张新的手写字体图片能够自动识别出对应的文字或数字.通过深度学习构建普通神经网络和卷积神经网络,处理手写字体数据.通 ...
- python+tensorflow CNN卷积神经网络手写字体识别
导入所需的库模块: import os import cv2 import numpy as np import tensorflow as tf2 import matplotlib.pyplot ...
- pytorch深度学习神经网络实现手写字体识别
利用平pytorch搭建简单的神经网络实现minist手写字体的识别,采用三层线性函数迭代运算,使得其具备一定的非线性转化与运算能力,其数学原理如下: 其具体实现代码如下所示:import torch ...
- 学习笔记CB009:人工神经网络模型、手写数字识别、多层卷积网络、词向量、word2vec...
人工神经网络,借鉴生物神经网络工作原理数学模型. 由n个输入特征得出与输入特征几乎相同的n个结果,训练隐藏层得到意想不到信息.信息检索领域,模型训练合理排序模型,输入特征,文档质量.文档点击历史.文档 ...
最新文章
- gym中render()函数在远端server运行的解决方案
- oracle中作业无法执行,Oracle运行JOB报ORA-27492:无法运行作业
- AutoDim:自动Embedding维度寻优,如何节省70%的存储空间同时还能大幅提效?
- jsr250-api_JSON处理的Java API(JSR-353)–流API
- spring框架(六)之拦截器
- android onscrolllistener判断到底部,判断RecyclerView是否滑动到底部
- 波音正在对737 Max进行软件升级 改善飞行员培训计划
- WSUS 3.0系列之二 补丁分发
- 2022年 电工杯B题5G 网络环境下 应急物资配送问题
- PuttyPsftp命令行实现自动登录
- 机器学习实战 KNN实战
- 计算机应用技术在医院的应用,计算机应用技术对医院信息化的影响探讨
- 共赴开源路,共筑新丰碑!2022云栖大会龙蜥操作系统峰会圆满落幕!
- mysql 1114错误_mysql – ERROR 1114(HY000):表’XXX’已满
- XP/LINUX双系统如何正常卸载LINUX
- IDEA2016 license server 激活
- 面对压力,逃避还是面对?
- 用Python读红楼梦之——一、词云绘制
- 2038问题及其解决方案
- 第12期《 蓄势待发 》1月刊
热门文章
- Oracle分页查询的两种方法
- UltraISO虚拟光驱使用:制作ISO镜像文件与刻录CD/DVD
- kubernetes flannel 网络
- Prometheus 普罗米修斯
- Promethus(普罗米修斯)
- JAVA防疫科普微课堂计算机毕业设计Mybatis+系统+数据库+调试部署
- [Windows]截图
- 【开发板资讯】友善推出mini6410 之后不久再推出tiny6410(mini6410和tiny6410有何不同?市场定位如何?)...
- springboot2 配置404、403、500等错误页面自动跳转
- CSS css选择器 jquery jQuery选择器的优先级 XXX XX X xxx xx x