目录

一:卷积神经网络基础概念

二:MNIST数据集

三:卷积神经网络搭建过程


一:卷积神经网络基础概念

普通的深层神经网络,层与层之间通过全连接进行稠密矩阵运算,矩阵中的权重系数比较多(参数多),影响效率且容易出现过拟合

卷积神经网络的结构:卷积层、激活函数、池化层、全连接层 

卷积层:将原始图片通过Filter(过滤器,权重矩阵,卷积核,观察窗口),分割出局部信息,过滤器经过多次平移取样(步长)形成一个个局部信息然后组成卷积层,卷积层中的每一个单位点对应前面层的局部信息;(卷积的意义:一个点与临近的点联系比较紧密,离得越远的点,联系越不紧密)当神经网络中的层数逐渐增加时,卷积层中的局部信息就会逐渐与全局信息产生联系;

过滤器大小一般设为3*3或5*5(奇数),步长1

(卷积核的计算过程:卷积核(权重矩阵)与输入图片的局部矩阵中的像素进行一一对应的线性相乘求和再加偏置得到卷积层中的一个单位值,卷积核进行平移继续得到卷积层中的全部值(2维)

可以有多个卷积核,多个卷积核的观察(计算)结果共同组成卷积层(3维)。如果图片是3通道,那么卷积核也是3通道,3个通道的计算结果再求和 加偏置形成卷积层中的单位点(卷积层形状的深度与通道数无关,只与卷积核的数量有关))

池化层:(下采样、欠采样,特征降维),减少矩阵的长和宽(也是通过观察窗口的形式实现),减少参数个数,避免过拟合。分为最大池化层和平均池化层(将观察窗口中的最大值或平均值作为其输出)

池化层中的观察窗口大小一般设为2*2,步长2

(池化层的计算过程:通过观察窗口截取卷积层,截取出的矩阵中的最大值(或平均值)作为池化层中的单位点,观察窗口进行平移形成整个池化层。池化只会减少卷积层形状的长和宽,并不会影响形状的深度)

激活函数:解决非线性划分问题,一般是一个非线性的函数,(神经网络的矩阵运算只是一个线性变化)

全连接层:前面的卷积和池化相当于做特征工程(并没有进行矩阵乘法,只是一一对应的线性相乘),后面的全连接相当于做真正的特征加权(矩阵乘法)

最后的全连接层在整个卷积神经网络中起到“分类器”的作用(如果卷积神经网络不是用于分类问题,那么可以不使用全连接层)

为什么要用Relu激活函数,而不用sigmoid激活函数?
第一,采用sigmoid激活函数,反向传播求误差梯度时,计算量相对大,而采用Relu激活函数,整个过程的计算量节省很多
第二,对于深层网络,sigmoid函数反向传播时,很容易就会出现梯度消失(梯度爆炸)的情况(求不出权重和偏置) 

二:MNIST数据集

获取地址如下,下载下来即可

http://yann.lecun.com/exdb/mnist/

三:卷积神经网络搭建过程

1 准备输入数据的占位符

# 网络搭建
# 特征标签占位符
# 图片大小28*28=784
xs = tf.placeholder(tf.float32, shape=[None, input_size])
# 目标类别:10个类别。 one-hot编码形式表示
ys = tf.placeholder(tf.float32, shape=[None, num_class])
# -1任意张图片 size(28*28) 1深度
# 对x进行形状的改变(变成4阶张量) [None, 784]--->[None, 28, 28, 1]
x_image = tf.reshape(xs, [-1, 28, 28, 1])

2 图片数据-》卷积层-》激活函数-》池化层

# CNN构建
# 图片数据-->卷积层-->激活函数-->池化层
# 第一层卷积层 卷积核5*5
# 随机初始化卷积核的矩阵权重   卷积核大小:5*5*1(1个通道,与输入图片通道数一致) 32个卷积核(决定卷积后形状的深度)
w_conv1 = tf.Variable(tf.random_normal(shape=[5, 5, 1, 32], stddev=0.01))
# 初始化偏置
b_conv1 = tf.Variable(tf.constant(0.01, shape=[32]))
# 卷积层
# 卷积、激活函数  输入的张量x_reshape必须四阶   [None, 28, 28, 1]---> [None, 28, 28, 32]
# padding="SAME"表示进行零填充,让卷积层的宽高与图片宽高一致(填充的围数自动计算,卷积核尺寸是奇数好计算)
# strides:卷积步长 上右下左 保证与原图像大小一致
conv1 = tf.nn.conv2d(x_image, w_conv1, strides=[1, 1, 1, 1], padding='SAME')
# 激活层
h_conv1 = tf.nn.relu(conv1 + b_conv1)
# 池化 窗口大小:2*2;步长:2    [None, 28, 28, 32]--->[None, 14, 14, 32]  池化只会改变形状的宽高,不会改变深度
h_pool1 = tf.nn.max_pool(h_conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

3 再次卷积 深层神经网络

# 再次卷积(深层神经网络) 卷积层-->激活函数-->池化层
# 随机初始化卷积核的矩阵权重  卷积核大小:5*5*32  64个卷积核
w_conv2 = tf.Variable(tf.random_normal(shape=[5, 5, 32, 64], stddev=0.01))
# 初始化偏置  64个偏置
b_conv2 = tf.Variable(tf.constant(0.01, shape=[64]))
# 卷积、激活函数   [None, 14, 14, 32]---> [None, 14, 14, 64]  padding="SAME":卷积只会改变形状的深度,不会改变宽高
conv2 = tf.nn.conv2d(h_pool1, w_conv2, strides=[1, 1, 1, 1], padding='SAME')
# 激活层 14*14*64
h_conv2 = tf.nn.relu(conv2 + b_conv2)
# 池化  窗口大小:2*2;步长:2   [None, 14, 14, 64]--->[None, 7, 7, 64]  池化只会改变形状的宽高,不会改变深度。
h_pool2 = tf.nn.max_pool(h_conv2, 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] (目标类别数10,one-hot编码)
# 随机初始化全连接的权重矩阵  目标类别数
w_fc1 = tf.Variable(tf.random_normal(shape=[7 * 7 * 64, 1024]))
# 初始化偏置
b_fc1 = tf.Variable(tf.constant(0.01, shape=[1024]))
# 输出的是矩阵 行不需要 列7*7*64 -1任意行
h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64])
# wx+b
h_fc1 = tf.matmul(h_pool2_flat, w_fc1) + b_fc1
# 激活
h_fc1 = tf.nn.relu(h_fc1)# 全连层2  分类 看作输出层 返回每一种情况的概率
w_fc2 = tf.Variable(tf.random_normal(shape=[1024, num_class]))
b_fc2 = tf.Variable(tf.constant(0.01, shape=[num_class]))
h_fc2 = tf.matmul(h_fc1, w_fc2) + b_fc2
# 进行矩阵运算得出每个样本的10个目标类别结果(可以通过softmax函数转换成10个目标类别的概率,最大的概率即为预测类别)
y_predict = tf.nn.softmax(h_fc2)

5 交叉熵损失计算

# 卷积神经网络模型定义结束
# 进行交叉熵损失计算
# 求出所有样本的交叉熵损失,然后tf.reduce_mean()计算平均值
# 构建损失函数
# 求平均交叉熵损失  y_predict是没有经过softmax函数处理的预测结果
loss = tf.reduce_mean(-tf.reduce_mean(ys * tf.log(y_predict), reduction_indices=[1]))
# 优化器 梯度下降优化损失
# 0.0001表示学习率 (学习率并不是一个超参数)(深层神经网络的学习率一般设很小)
Optimizer = tf.train.AdamOptimizer(0.0001).minimize(loss)

6 开启会话 迭代训练

# 定义一个初始化变量的op
init = tf.global_variables_initializer()# 创建会话
with tf.Session() as sess:# 初始化变量sess.run(init)# 迭代训练,更新参数 (迭代1000次)for i in range(1000):# 取出训练集的特征值和目标值 (每次迭代取出100个样本)batch_x, batch_y = mnist_data.train.next_batch(100)# 运行Optimizer训练优化 (feed_dict:用实时的训练数据填充占位符)sess.run(Optimizer, feed_dict={xs: batch_x, ys: batch_y})# train_loss = sess.run(loss, feed_dict={xs: batch_x, ys: batch_y})# print(train_loss)print("训练第%d步,准确率为:%f" % (i, sess.run(loss, feed_dict={xs: batch_x, ys: batch_y})))

测试如下,准确率在0.005左右

完整源码分享

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data# 读取数据
# TensorFlow自带的数据集(手写数字图片,55000个训练样本,10000个测试样本,图片尺寸28*28=784)
mnist_data = input_data.read_data_sets("MNIST_data/", one_hot=True)
# print(mnist_data, type(mnist_data))input_size = 28 * 28
num_class = 10# 网络搭建
# 特征标签占位符
# 图片大小28*28=784
xs = tf.placeholder(tf.float32, shape=[None, input_size])
# 目标类别:10个类别。 one-hot编码形式表示
ys = tf.placeholder(tf.float32, shape=[None, num_class])
# -1任意张图片 size(28*28) 1深度
# 对x进行形状的改变(变成4阶张量) [None, 784]--->[None, 28, 28, 1]
x_image = tf.reshape(xs, [-1, 28, 28, 1])# CNN构建
# 图片数据-->卷积层-->激活函数-->池化层
# 第一层卷积层 卷积核5*5
# 随机初始化卷积核的矩阵权重   卷积核大小:5*5*1(1个通道,与输入图片通道数一致) 32个卷积核(决定卷积后形状的深度)
w_conv1 = tf.Variable(tf.random_normal(shape=[5, 5, 1, 32], stddev=0.01))
# 初始化偏置
b_conv1 = tf.Variable(tf.constant(0.01, shape=[32]))
# 卷积层
# 卷积、激活函数  输入的张量x_reshape必须四阶   [None, 28, 28, 1]---> [None, 28, 28, 32]
# padding="SAME"表示进行零填充,让卷积层的宽高与图片宽高一致(填充的围数自动计算,卷积核尺寸是奇数好计算)
# strides:卷积步长 上右下左 保证与原图像大小一致
conv1 = tf.nn.conv2d(x_image, w_conv1, strides=[1, 1, 1, 1], padding='SAME')
# 激活层
h_conv1 = tf.nn.relu(conv1 + b_conv1)
# 池化 窗口大小:2*2;步长:2    [None, 28, 28, 32]--->[None, 14, 14, 32]  池化只会改变形状的宽高,不会改变深度
h_pool1 = tf.nn.max_pool(h_conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')# 再次卷积(深层神经网络) 卷积层-->激活函数-->池化层
# 随机初始化卷积核的矩阵权重  卷积核大小:5*5*32  64个卷积核
w_conv2 = tf.Variable(tf.random_normal(shape=[5, 5, 32, 64], stddev=0.01))
# 初始化偏置  64个偏置
b_conv2 = tf.Variable(tf.constant(0.01, shape=[64]))
# 卷积、激活函数   [None, 14, 14, 32]---> [None, 14, 14, 64]  padding="SAME":卷积只会改变形状的深度,不会改变宽高
conv2 = tf.nn.conv2d(h_pool1, w_conv2, strides=[1, 1, 1, 1], padding='SAME')
# 激活层 14*14*64
h_conv2 = tf.nn.relu(conv2 + b_conv2)
# 池化  窗口大小:2*2;步长:2   [None, 14, 14, 64]--->[None, 7, 7, 64]  池化只会改变形状的宽高,不会改变深度。
h_pool2 = tf.nn.max_pool(h_conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')# 全连接层  矩阵乘法:[None, 7, 7, 64]--->[None, 7*7*64]*[7*7*64, 10] + [10] = [None, 10] (目标类别数10,one-hot编码)
# 随机初始化全连接的权重矩阵  目标类别数
w_fc1 = tf.Variable(tf.random_normal(shape=[7 * 7 * 64, 1024]))
# 初始化偏置
b_fc1 = tf.Variable(tf.constant(0.01, shape=[1024]))
# 输出的是矩阵 行不需要 列7*7*64 -1任意行
h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64])
# wx+b
h_fc1 = tf.matmul(h_pool2_flat, w_fc1) + b_fc1
# 激活
h_fc1 = tf.nn.relu(h_fc1)# 全连层2  分类 看作输出层 返回每一种情况的概率
w_fc2 = tf.Variable(tf.random_normal(shape=[1024, num_class]))
b_fc2 = tf.Variable(tf.constant(0.01, shape=[num_class]))
h_fc2 = tf.matmul(h_fc1, w_fc2) + b_fc2
# 进行矩阵运算得出每个样本的10个目标类别结果(可以通过softmax函数转换成10个目标类别的概率,最大的概率即为预测类别)
y_predict = tf.nn.softmax(h_fc2)# 卷积神经网络模型定义结束
# 进行交叉熵损失计算
# 求出所有样本的交叉熵损失,然后tf.reduce_mean()计算平均值
# 构建损失函数
# 求平均交叉熵损失  y_predict是没有经过softmax函数处理的预测结果
loss = tf.reduce_mean(-tf.reduce_mean(ys * tf.log(y_predict), reduction_indices=[1]))
# 优化器 梯度下降优化损失
# 0.0001表示学习率 (学习率并不是一个超参数)(深层神经网络的学习率一般设很小)
Optimizer = tf.train.AdamOptimizer(0.0001).minimize(loss)# 定义一个初始化变量的op
init = tf.global_variables_initializer()# 创建会话
with tf.Session() as sess:# 初始化变量sess.run(init)# 迭代训练,更新参数 (迭代1000次)for i in range(1000):# 取出训练集的特征值和目标值 (每次迭代取出100个样本)batch_x, batch_y = mnist_data.train.next_batch(100)# 运行Optimizer训练优化 (feed_dict:用实时的训练数据填充占位符)sess.run(Optimizer, feed_dict={xs: batch_x, ys: batch_y})# train_loss = sess.run(loss, feed_dict={xs: batch_x, ys: batch_y})# print(train_loss)print("训练第%d步,准确率为:%f" % (i, sess.run(loss, feed_dict={xs: batch_x, ys: batch_y})))

TensorFlow 手写实现卷积神经网络CNN相关推荐

  1. 【TensorFlow实战笔记】卷积神经网络CNN实战-cifar10数据集(tensorboard可视化)

    IDE:pycharm Python: Python3.6 OS: win10 tf : CPU版本 代码可在github中下载,欢迎star,谢谢 CNN-CIFAR-10 一.CIFAR10数据集 ...

  2. 手写经典卷积神经网络-LeNet

    目录 论文: keras torch版本: 训练: 测试和可视化 论文: 论文名:Gradient-Based Learning Applied to Document Recognition ker ...

  3. 手写经典卷积神经网络-AlexNet

    目录 论文: torch实现: 数据集分割处理脚本spile_data.py 定义一个AlexNet网络model.py 训练脚本train.py 预测脚本predict.py 论文: ImageNe ...

  4. python卷积神经网络cnn的训练算法_【深度学习系列】卷积神经网络CNN原理详解(一)——基本原理...

    上篇文章我们给出了用paddlepaddle来做手写数字识别的示例,并对网络结构进行到了调整,提高了识别的精度.有的同学表示不是很理解原理,为什么传统的机器学习算法,简单的神经网络(如多层感知机)都可 ...

  5. 基于卷积神经网络 CNN 的猫狗识别详细过程

    目录 一.卷积神经网络(CNN) 1.1 卷积 1.2 前馈神经网络 1.3 卷积神经网络(CNN) 二.配置环境 三.猫狗数据分类建模 3.1 猫狗图像预处理 3.2 猫狗分类的实例--基准模型 3 ...

  6. 【卷积神经网络CNN 实战案例 GoogleNet 实现手写数字识别 源码详解 深度学习 Pytorch笔记 B站刘二大人 (9.5/10)】

    卷积神经网络CNN 实战案例 GoogleNet 实现手写数字识别 源码详解 深度学习 Pytorch笔记 B站刘二大人 (9.5/10) 在上一章已经完成了卷积神经网络的结构分析,并通过各个模块理解 ...

  7. 【人工智能实验】卷积神经网络CNN框架的实现与应用-手写数字识别

    目录 实验六 卷积神经网络CNN框架的实现与应用 一.实验目的 二.实验原理 三.实验结果 1.调整学习率.epochs以及bacth_size这三个参数,分别观察参数的变化对于实验结果的影响. 2. ...

  8. TensorFlow手写数字识别与一步一步实现卷积神经网络(附代码实战)

    编译 | fendouai 编辑 | 安可 [导读]:本篇文章将说明 TensorFlow 手写数字识别与一步一步实现卷积神经网络.欢迎大家点击上方蓝字关注我们的公众号:深度学习与计算机视觉. 手写数 ...

  9. 【图像识别】基于卷积神经网络CNN手写数字识别matlab代码

    1 简介 针对传统手写数字的随机性,无规律性等问题,为了提高手写数字识别的检测准确性,本文在研究手写数字区域特点的基础上,提出了一种新的手写数字识别检测方法.首先,对采集的手写数字图像进行预处理,由于 ...

最新文章

  1. 苹果让Transformer抛弃注意力机制,一切只为效率,项目已开源丨华人一作
  2. 视频jourk--hadoop2.2.0(第一个2.x的正式版本)框架介绍:笔记
  3. 分布式检索系统的简单设计
  4. 做一个p2p打洞的C#程序
  5. 使用nomad部署mysql
  6. 怎么判断前轮左右的位置_如何判定汽车前面左右轮的位置?大家有什么经验?...
  7. CocosPods 引入项目,哪些文件需要上传到服务器呢?
  8. 改进程架构,Edge优化浏览器内存问题
  9. Flink的Window
  10. CSS3 弹性盒子模型
  11. 如何解决Windows 10屏幕字体缩放模糊问题
  12. MySql的基本操作流程-SAE的MySQL-PHP
  13. CentOS中一些基本的操作记录
  14. 出现java.sql.SQLException: No suitable driver的几种解决办法
  15. 视频会议之BigBlueButton
  16. Android调用长截屏,Android实现长截屏功能
  17. bch纠错码 码长8_BCH码-BCH码原理-BCH码分类-BCH码的应用-什么是BCH码-测控百科-CK365测控网...
  18. Copula、CoVaR、Garch、DCC、藤Vine、BEKK、SV、ECM
  19. 作为一枚程序员,每天必用的软件有哪些?
  20. T级攻防:大规模DDOS防御架构

热门文章

  1. 常用计算机字体的后缀名是,自考计算机应用基础试题及参考答案
  2. Kakao拟16亿美元收购韩国最大音乐流媒体服务
  3. 云台山茶旅集团各分子版块日新月(2月20日)
  4. 倍福PLC模拟量输入模块的使用方法
  5. 如何在Chrome浏览器下清除DNS缓存
  6. [MakeFile教程-09] 隐含规则
  7. NTP时间同步服务器客户端、服务端的安装以及配置文件的配置
  8. 配置photon服务器,unity连接Photon
  9. 【vue系列-03】vue的计算属性,列表,监视属性及原理
  10. efi启动修复linux引导文件夹,一次修复linux的efi引导的集中方法总结记录