社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

[Python人工智能] 八.卷积神经网络CNN原理详解及TensorFlow编写CNN

Eastmount • 5 年前 • 589 次点击  

从本专栏开始,作者正式开始研究Python深度学习、神经网络及人工智能相关知识。前一篇文章介绍了什么是过拟合,并采用droput解决神经网络中过拟合的问题,以TensorFlow和sklearn的load_digits为案例讲解;本篇文章详细讲解了卷积神经网络CNN原理,并通过TensorFlow编写CNN实现了MNIST分类学习案例。本专栏主要结合作者之前的博客、AI经验和"莫烦大神"的视频介绍,后面随着深入会讲解更多的Python人工智能案例及应用。

基础性文章,希望对您有所帮助,如果文章中存在错误或不足之处,还请海涵~作者作为人工智能的菜鸟,希望大家能与我在这一笔一划的博客中成长起来。写了这么多年博客,尝试第一个付费专栏,但更多博客尤其基础性文章,还是会继续免费分享,但该专栏也会用心撰写,望对得起读者,共勉!

在这里插入图片描述

代码下载地址: https://github.com/eastmountyxz/AI-for-TensorFlow

同时推荐前面作者另外三个Python系列文章。从2014年开始,作者主要写了三个Python系列文章,分别是基础知识、网络爬虫和数据分析。2018年陆续增加了Python图像识别和Python人工智能专栏。

在这里插入图片描述

前文:
[Python人工智能] 一.TensorFlow2.0环境搭建及神经网络入门
[Python人工智能] 二.TensorFlow基础及一元直线预测案例
[Python人工智能] 三.TensorFlow基础之Session、变量、传入值和激励函数
[Python人工智能] 四.TensorFlow创建回归神经网络及Optimizer优化器
[Python人工智能] 五.Tensorboard可视化基本用法及绘制整个神经网络
[Python人工智能] 六.TensorFlow实现分类学习及MNIST手写体识别案例
[Python人工智能] 七.什么是过拟合及dropout解决神经网络中的过拟合问题


一.卷积神经网络原理

1.什么是CNN

一般的神经网络在理解图片信息的时候还是有不足之处,这时卷积神经网络就成为了计算机处理图片的助推器。卷积神经网络的英文是Convolutional Neural Network,简称CNN。它通常应用于图像识别和语音识等领域,并能给出更优秀的结果,也可以应用于视频分析、机器翻译、自然语言处理、药物发现等领域。著名的阿尔法狗让计算机看懂围棋就是基于卷积神经网络的。

神经网络是由很多神经层组成,每一层神经层中存在很多神经元,这些神经元是识别事物的关键,当输入是图片时,其实就是一堆数字。

在这里插入图片描述

首先,卷积是什么意思呢?卷积是指不在对每个像素做处理,而是对图片区域进行处理,这种做法加强了图片的连续性,看到的是一个图形而不是一个点,也加深了神经网络对图片的理解。

在这里插入图片描述

卷积神经网络批量过滤器,持续不断在图片上滚动搜集信息,每一次搜索都是一小块信息,整理这一小块信息之后得到边缘信息。比如第一次得出眼睛鼻子轮廓等,再经过一次过滤,将脸部信息总结出来,再将这些信息放到全神经网络中进行训练,反复扫描最终得出的分类结果。如下图所示,猫的一张照片需要转换为数学的形式,这里采用长宽高存储,其中黑白照片的高度为1,彩色照片的高度为3(RGB)。

在这里插入图片描述

过滤器搜集这些信息,将得到一个更小的图片,再经过压缩增高信息嵌入到普通神经层上,最终得到分类的结果,这个过程即是卷积。Convnets是一种在空间上共享参数的神经网络,如下图所示,它将一张RGB图片进行压缩增高,得到一个很长的结果。

在这里插入图片描述

近几年神经网络飞速发展,其中一个很重要的原因就是CNN卷积神经网络的提出,这也是计算机视觉处理的飞跃提升。关于TensorFlow中的CNN,Google公司也出了一个非常精彩的视频教程,也推荐大家去学习。

Google官方卷积神经网络介绍视频 - 优达学城


2.CNN原理

本文主要讲解如何去应用CNN,下面我们先简单看看CNN是如何处理信息的。这里参考Google官方视频介绍,强烈推荐大家学习。

假设你有一张小猫咪的照片,如下图所示,它可以被表示为一个博饼,它有宽度(width)和高度(height),并且由于天然存在红绿蓝三色,它还拥有RGB厚度(depth),此时你的输入深度为3。

在这里插入图片描述

假设我们现在拿出图片的一小块,运行一个具有K个输出的小神经网络,像图中一样把输出表示为垂直的一小列。

在这里插入图片描述

在不改变权重的情况下,通过小神经网络滑动扫遍整个图片,就像我们拿着刷子刷墙一样水平垂直的滑动。

在这里插入图片描述

此时,输出端画出了另一幅图像,如下图中红色区域所示。它与之前的宽度和高度不同,更重要的是它跟之前的深度不同,而不是仅仅只有红绿蓝,现在你得到了K个颜色通道,这种操作称为——卷积。

在这里插入图片描述

如果你的块大小是整张图片,那它跟普通的神经网络层没有任何区别,正是由于我们使用了小块,我们有很多小块在空间中共享较少的权重。卷积不在对每个像素做处理,而是对图片区域进行处理,这种做法加强了图片的连续性,也加深了神经网络对图片的理解。

在这里插入图片描述

一个卷积网络是组成深度网络的基础,我们将使用数层卷积而不是数层的矩阵相乘。如下图所示,让它形成金字塔形状,金字塔底是一个非常大而浅的图片,仅包括红绿蓝,通过卷积操作逐渐挤压空间的维度,同时不断增加深度,使深度信息基本上可以表示出复杂的语义。同时,你可以在金字塔的顶端实现一个分类器,所有空间信息都被压缩成一个标识,只有把图片映射到不同类的信息保留,这就是CNN的总体思想。

上图的具体流程如下:

  • 首先,这是有一张彩色图片,它包括RGB三原色分量,图像的长和宽为256*256,三个层面分别对应红(R)、绿(G)、蓝(B)三个图层,也可以看作像素点的厚度。
  • 其次,CNN将图片的长度和宽度进行压缩,变成128 128 16的方块,压缩的方法是把图片的长度和宽度压小,从而增高厚度。
  • 再次,继续压缩至64 64 64,直至32 32 256,此时它变成了一个很厚的长条方块,我们这里称之为分类器Classifier。该分类器能够将我们的分类结果进行预测,MNIST手写体数据集预测结果是10个数字,比如[0,0,0,1,0,0,0,0,0,0]表示预测的结果是数字3,Classifier在这里就相当于这10个序列。
  • 最后,CNN通过不断压缩图片的长度和宽度,增加厚度,最终会变成了一个很厚的分类器,从而进行分类预测。

在这里插入图片描述

如果你想实现它,必须还要正确实现很多细节。此时,你已经接触到了块和深度的概念,块(PATCH)有时也叫做核(KERNEL),如下图所示,你堆栈的每个薄饼都被叫做特征图(Feature Map),这里把三个特性映射到K个特征图中,PATCH/KERNEL的功能是从图片中抽离一小部分进行分析,每次抽离的小部分都会变成一个长度、一个宽度、K个厚度的数列。

在这里插入图片描述

另一个你需要知道的概念是——步幅(STRIDE)。它是当你移动滤波器或抽离时平移的像素的数量,每一次跨多少步去抽离图片中的像素点。

在这里插入图片描述

如果步幅STRIDE等于1,表示每跨1个像素点抽离一次,得到的尺寸基本上和输入相同。

在这里插入图片描述

如果步幅STRIDE等于2,表示每次跨2个像素点抽离,意味着变为一半的尺寸。它收集到的信息就会被缩减,图片的长度和宽度被压缩了,压缩合并成更小的一块立方体。

在这里插入图片描述

压缩完之后再合并成一个立方体,它就是更小的一块立方体,包含了图片中的所有信息。

在这里插入图片描述

抽离图片信息的方式称为PADDING(填充),一般分为两种:

  • VALID PADDING: 抽出来这层比原先那层图片宽和长裁剪了一点,抽取的内容全部是图片内的。
  • SAME PADDING: 抽离出的那层与之前的图片一样的长和宽,抽取的内容部分再图片外,图片外的值用0来填充。

在这里插入图片描述

研究发现,卷积过程会丢失一些信息,比如现在想跨2步去抽离原始图片的重要信息,形成长宽更小的图片,该过程中可能会丢失重要的图片信息。为了解决这个问题,通过POOLING(持化)可以避免。其方法是:卷积时不再压缩长宽,尽量保证更多信息,压缩工作交给POOLING。经过图片到卷积,持化处理卷积信息,再卷积再持化,将结果传入两层全连接神经层,最终通过分类器识别猫或狗。

在这里插入图片描述

总结:整个CNN从下往上依次经历“图片->卷积->持化->卷积->持化->结果传入两层全连接神经层->分类器”的过程,最终实现一个CNN的分类处理。

  • IMAGE 图片
  • CONVOLUTION 图层
  • MAX POOLING 更好地保存原图片的信息
  • CONVOLUTION 图层
  • MAX POOLING 更好地保存原图片的信息
  • FULLY CONNECTED 神经网络隐藏层
  • FULLY CONNECTED 神经网络隐藏层
  • CLASSIFIER 分类器

在这里插入图片描述

写到这里,CNN的基本原理讲解完毕,希望大家对CNN有一个初步的理解。同时建议大家处理神经网络时,先用一般的神经网络去训练它,如果得到的结果非常好,就没必要去使用CNN,因为CNN结构比较复杂。


二.TensorFlow实现CNN

接着我们讲解如何在TensorFlow代码中编写CNN。之前我们用一般的神经网络来预测MNIST手写数字时,其准确率能达到87.78%。但该准确率相对目前的技术来说,是非常低的,我们需要编写CNN来实现,它能提升到96%左右。

第一步,打开Anaconda,然后选择已经搭建好的“tensorflow”环境,运行Spyder。

在这里插入图片描述


第二步,导入扩展包。

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
  • 1
  • 2

第三步,下载数据集。
由于MNIST数据集是TensorFlow的示例数据,所以我们只需要下面一行代码,即可实现数据集的读取工作。如果数据集不存在它会在线下载,如果数据集已经被下载,它会被直接调用。

# 下载数据集 数字1到10
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
  • 1
  • 2

获取的数据如下图所示:

在这里插入图片描述


第四步,定义compute_accuracy()函数,输出的准确度result为该函数返回的结果。
mnist分为train data(训练数据集)和test data(测试数据集),如果整个数据集拿去训练,会造成人为的误差,分好成两个独立的事件效果会更好。这里定义compute_accuracy()函数计算准确度,代码如下:

#-------------------------------定义计算准确度函数------------------------------
# 参数:预测xs和预测ys
def compute_accuracy(v_xs, v_ys):
    # 定义全局变量
    global prediction
    # v_xs数据填充到prediction变量中 生成预测值0到1之间的概率
    y_pre = sess.run(prediction, feed_dict={xs:v_xs,keep_prob: 1})
    # 比较预测最大值(y_pre)和真实最大值(v_ys)的差别 如果等于就是预测正确,否则错误
    correct_prediction = tf.equal(tf.argmax(y_pre,1), tf.argmax(v_ys,1))
    # 计算正确的数量
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    # 输出结果为百分比 百分比越高越准确
    result = sess.run(accuracy, feed_dict={xs:v_xs, ys:v_ys, keep_prob:1})
    


    
return result
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

接着我们需要编写定义weight、bias、conv2d、max_pool_2x2等函数。

在这里插入图片描述



第五步,定义权重和误差变量。

#---------------------------------定义权重和误差变量------------------------------
# 输入shape返回变量定义的参数
def weight_variable(shape):
    # 产生截断正态分布随机数
    initial = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(initial)
    
def bias_variable(shape):
    # 误差初始值定义为0.1
    initial = tf.constant(0.1, shape=shape)
    return tf.Variable(initial)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

第六步,定义卷积神经网络层。

#---------------------------------定义卷积神经网络层------------------------------
# 定义二维CNN x表示输入值或图片的值 W表示权重
def conv2d(x, W):
    # 输入x表示整张图片的信息 权重W strides表示步长跨度 [1,x_movement,y_movement,1]
    # strides:一个长度为4的列表 第一个和最后一个元素为1 第二个为元素是水平x方向的跨度 第三个元素为垂直y方向跨度
    # padding包括两种形式 VALID和SAME
    return tf.nn.conv2d(x, W, strides=[1,1,1,1], padding='SAME')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

抽离图片信息的方式成为PADDING,这里使用“SAME PADDING”,抽离出的那层与之前的图片一样的长和宽。


第七步,为了防止跨度太大,丢失东西太多,这里添加了POOLING处理,减小跨度。最终得到结果的形状都一样,但它能保留更多的图片信息。

在这里插入图片描述

conv2d()函数和max_pool_2x2()比较类似,但是con2d阶段保留了原始长度和宽度(strides=[1,1,1,1]),而在pooling阶段减小长度和宽度(strides=[1,2,2,1])。

#------------------------------------定义POOLING---------------------------------
def max_pool_2x2(x):
    # Must have strides[0] = striders[3] = 1
    # x_movement和y_movement隔两个步长移动一次 从而压缩整幅图片的长和宽
    return tf.nn.max_pool(x, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
  • 1
  • 2
  • 3
  • 4
  • 5

第八步,定义placeholder,用于传入值xs和ys至神经网络。

# 设置传入的值xs和ys
xs = tf.placeholder(tf.float32, [None, 784])  #每张图片28*28=784个点
ys = tf.placeholder(tf.float32, [None, 10])   #每个样本有10个输出


    

# keeping probability
keep_prob = tf.placeholder(tf.float32)

# 形状修改
# xs包括了所有的图片样本 -1表示图片个数维度暂时不管(后续补充) 
# 28*28表示像素点 1表示信道(该案例图片黑白为1,彩色为3)
x_image = tf.reshape(xs, [-1,28,28,1])
print(x_image.shape) #[n_samples,28,28,1]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

接下来我们就开始讲解如何添加神经层。


第九步,增加神经层 conv1 layer。

小方块的长度和宽度是5,in size为1是图片的厚度,输出的高度是32。

在这里插入图片描述

h_conv1输出的大小为28 28 32,因为padding采用“SAME”的形式,W_conv1输出值为32,故厚度也为32,长度和宽度相同为28。而由于POOLING处理设置的strides步长为2,故其输出大小也有变化,其结果为14 14 32。核心代码如下:

#-------------------------------增加神经层 conv1 layer------------------------------
# 定义权重
W_conv1 = weight_variable([5,5,1,32]) #patch 5*5, input size 1, output size 32
# 定义bias
b_conv1 = bias_variable([32]) #32个长度

# 搭建CNN的第一层
# 嵌套一个relu非线性化激励处理  计算 = x_image输入*权重 + 误差
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1) # output size 28*28*32
# POOLING处理
h_pool1 = max_pool_2x2(h_conv1)                          # output size 14*14*32
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

第十步,通过同样的方法定义conv2 layer。

W_conv2定义的patch为5*5,传入大小为32,传出大小为64,不断将其变厚,类似于下图所示。图片最早的厚度为1(MNIST数据集是黑白图片,如果是彩色则为3),接着第一层厚度变成32,第三层厚度增长为64。

在这里插入图片描述

此时h_conv2的输出结果为14 14 64,第二层POOLING处理会继续缩小一半,h_pool2输出结果为7 7 64,高度不变。

#-------------------------------增加神经层 conv2 layer------------------------------
# 定义权重
W_conv2 = weight_variable([5,5,32,64]) #patch 5*5, input size 32, output size 64
# 定义bias
b_conv2 = bias_variable([64]) #64个长度
# 搭建CNN的第二层
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2) # output size 14*14*64
# POOLING处理
h_pool2 = max_pool_2x2(h_conv2)                          # output size 7*7*64
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

接下来我们开始定义func1 layer和func2layer。


第十一步,定义func1 layer,即第一个全连接神经层。

定义权重,输入值为conv2 layer的输出值7 7 64,输出值为1024,让其变得更高更厚。

#-------------------------------增加神经层 func1 layer------------------------------
# 定义权重 输入值为conv2 layer的输出值7*7*64 输出为1024
W_fc1 = weight_variable([7*7*64, 1024])
# 定义bias
b_fc1 = bias_variable([1024])


    
 #1024个长度
# 将h_pool2输出值7*7*64转换为一维数据 [n_samples,7,7,64]->>[n_samples,7*7*64]
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64]) #-1表示样本数
# 乘法
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
# 解决过拟合
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

第十二步,进行最后一层的Layer处理。

#-------------------------------增加神经层 func2 layer------------------------------
# 定义权重 输入值为1024 输出为10对应10个数字
W_fc2 = weight_variable([1024, 10])
# 定义bias
b_fc2 = bias_variable([10])
# 预测 使用softmax计算概率
prediction = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这里简单总结下神经网络:

  • conv1 layer:经过卷积和POOLING处理,最终输出14 14 32
  • conv2 layer:经过卷积和POOLING处理,最终输出7 7 64
  • func1 layer:平常使用的神经网络,输入7 7 64,最终输出1024
  • func2 layer:平常使用的神经网络,输入1024,最终输出10,代表10个数字,即为prediction


第十三步,定义误差loss和训练。
这里使用的优化器是AdamOptimizer()函数,其学习效率比GradientDescentOptimizer()更高,学习效率设置为0.0001。

# 预测值与真实值误差 平均值->求和->ys*log(prediction)
cross_entropyloss = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction), 
                     reduction_indices=[1]))  #loss
# 训练学习 学习效率设置为0.0001
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropyloss) #减小误差
  • 1
  • 2
  • 3
  • 4
  • 5

第十四步,初始化操作。

# 定义Session
sess = tf.Session()
# 初始化
init = tf.initialize_all_variables()
sess.run(init)
  • 1
  • 2
  • 3
  • 4
  • 5

第十五步,神经网络分类学习。

for i in range(1000):
    # 提取一部分的xs和ys
    batch_xs, batch_ys = mnist.train.next_batch(100) #从下载好的数据集提取100个样本
    # 训练
    sess.run(train_step, feed_dict={xs:batch_xs, ys:batch_ys})
    # 每隔50步输出一次结果
    if i % 50 == 0:
        # 计算准确度
        print(compute_accuracy(


    

                mnist.test.images, mnist.test.labels))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

最终完整代码如下:

# -*- coding: utf-8 -*-
"""
Created on Fri Dec 20 14:27:01 2019
@author: xiuzhang Eastmount CSDN
"""
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

# 下载数据集 数字1到10
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)

#-------------------------------定义计算准确度函数------------------------------
# 参数:预测xs和预测ys
def compute_accuracy(v_xs, v_ys):
    # 定义全局变量
    global prediction
    # v_xs数据填充到prediction变量中 生成预测值0到1之间的概率
    y_pre = sess.run(prediction, feed_dict={xs:v_xs,keep_prob: 1})
    # 比较预测最大值(y_pre)和真实最大值(v_ys)的差别 如果等于就是预测正确,否则错误
    correct_prediction = tf.equal(tf.argmax(y_pre,1), tf.argmax(v_ys,1))
    # 计算正确的数量
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    # 输出结果为百分比 百分比越高越准确
    result = sess.run(accuracy, feed_dict={xs:v_xs, ys:v_ys, keep_prob:1})
    return result


#---------------------------------定义权重和误差变量------------------------------
# 输入shape返回变量定义的参数
def weight_variable(shape):
    # 产生截断正态分布随机数
    initial = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(initial)
    
def bias_variable(shape):
    # 误差初始值定义为0.1
    initial = tf.constant(0.1, shape=shape)
    return tf.Variable(initial)

#---------------------------------定义卷积神经网络层------------------------------
# 定义二维CNN x表示输入值或图片的值 W表示权重
def conv2d(x, W):
    # 输入x表示整张图片的信息 权重W strides表示步长跨度 [1,x_movement,y_movement,1]
    # strides:一个长度为4的列表 第一个和最后一个元素为1 第二个为元素是水平x方向的跨度 第三个元素为垂直y方向跨度
    # padding包括两种形式 VALID和SAME
    return tf.nn.conv2d(x, W, strides=[1,1,1,1], padding='SAME')

#------------------------------------定义POOLING---------------------------------
def max_pool_2x2(x):
    # Must have strides[0] = striders[3] = 1
    # x_movement和y_movement隔两个步长移动一次 从而压缩整幅图片的长和宽
    return tf.nn.max_pool(x, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
    



    
#-----------------------------定义placeholder输入至神经网络-------------------------
# 设置传入的值xs和ys
xs = tf.placeholder(tf.float32, [None, 784])  #每张图片28*28=784个点
ys = tf.placeholder(tf.float32, [None, 10])   #每个样本有10个输出
# keeping probability
keep_prob = tf.placeholder(tf.float32)

# 形状修改
# xs包括了所有的图片样本 -1表示图片个数维度暂时不管(后续补充) 
# 28*28表示像素点 1表示信道(该案例图片黑白为1,彩色为3)
x_image = tf.reshape(xs, [-1,28,28,1])
print(x_image.shape) #[n_samples,28,28,1]
    
#-------------------------------增加神经层 conv1 layer------------------------------
# 定义权重
W_conv1 = weight_variable([5,5,1,32]) #patch 5*5, input size 1, output size 32
# 定义bias
b_conv1 = bias_variable([32]) #32个长度

# 搭建CNN的第一层
# 嵌套一个relu非线性化激励处理  计算 = x_image输入*权重 + 误差
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1) # output size 28*28*32
# POOLING处理
h_pool1 = max_pool_2x2(h_conv1)                          # output size 14*14*32


#-------------------------------增加神经层 conv2 layer------------------------------
# 定义权重
W_conv2 = weight_variable([5,5,32,64]) #patch 5*5, input size 32, output size 64
# 定义bias
b_conv2 = bias_variable([64]) #64个长度
# 搭建CNN的第二层
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2) # output size 14*14*64
# POOLING处理
h_pool2 = max_pool_2x2(h_conv2)                          # output size 7*7*64


#-------------------------------增加神经层 func1 layer------------------------------
# 定义权重 输入值为conv2 layer的输出值7*7*64 输出为1024
W_fc1 = weight_variable([7*7*64, 1024])
# 定义bias
b_fc1 = bias_variable([1024]) #1024个长度
# 将h_pool2输出值7*7*64转换为一维数据 [n_samples,7,7,64]->>[n_samples,7*7*64]
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64]) #-1表示样本数
# 乘法
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
# 解决过拟合
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

#-------------------------------增加神经层 func2 layer------------------------------
# 定义权重 输入值为1024 输出为10对应10个数字
W_fc2 = weight_variable([1024, 10])
# 定义bias
b_fc2 = bias_variable([10])
# 预测 使用softmax计算概率
prediction = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2)


    
 + b_fc2)


#------------------------------定义loss和训练-------------------------------
# 预测值与真实值误差 平均值->求和->ys*log(prediction)
cross_entropyloss = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction), 
                     reduction_indices=[1]))  #loss
# 训练学习 学习效率设置为0.0001
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropyloss) #减小误差


#-----------------------------------初始化-----------------------------------
# 定义Session
sess = tf.Session()
# 初始化
init = tf.initialize_all_variables()
sess.run(init)

#---------------------------------神经网络学习---------------------------------
for i in range(1000):
    # 提取一部分的xs和ys
    batch_xs, batch_ys = mnist.train.next_batch(100) #从下载好的数据集提取100个样本
    # 训练
    sess.run(train_step, feed_dict={xs:batch_xs, ys:batch_ys, keep_prob:0.5})
    # 每隔50步输出一次结果
    if i % 50 == 0:
        # 计算准确度
        print(compute_accuracy(
                mnist.test.images, mnist.test.labels))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137

接着运行代码,CPU基本上满负荷运转。

在这里插入图片描述

最终输出结果如下图所示,可以看到,最早预测的准确度结果非常低为6.78%,最后提升到了96.92%,其结果高于之前的一般神经网络的结果87.79%(第六篇博客),由此可见TensorFlow CNN的分类学习效果还不错。

在这里插入图片描述

0.0678
0.8096
0.8839
0.9119
0.9266
0.9361
0.9441
0.9496
0.9505
0.9561
0.9566
0.9616
0.9625
0.9644
0.9648
0.9668
0.9689
0.9698
0.9709
0.9692
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

三.总结

写到这里,这篇文章就结束了。本文详细介绍了卷积神经网络CNN的基本原理,并通过TensorFlow实现CNN卷积神经网络,结合MNIST手写体识别数据集进行分类学习。最后,希望这篇基础性文章对您有所帮助,如果文章中存在错误或不足之处,还请海涵~作为人工智能的菜鸟,我希望自己能不断进步并深入,后续将它应用于图像识别、网络安全、对抗样本等领域,指导大家撰写简单的学术论文,一起加油!

PS:这是作者的第一个付费专栏,会非常用心的去撰写,希望能对得起读者的9块钱。本来只想设置1快的,但CSDN固定了价格。写了八年的免费文章,这也算知识付费的一个简单尝试吧!毕竟读博也不易,写文章也花费时间和精力,但作者更多的文章会免费分享。如果您购买了该专栏,有Python数据分析、图像处理、人工智能、网络安全的问题,我们都可以深入探讨,尤其是做研究的同学,共同进步~

(By:Eastmount 2019-12-20 晚上9点夜于珞珈山 http://blog.csdn.net/eastmount/ )


作者theano人工智能系列:
[Python人工智能] 一.神经网络入门及theano基础代码讲解
[Python人工智能] 二.theano实现回归神经网络分析
[Python人工智能] 三.theano实现分类神经网络及机器学习基础
[Python人工智能] 四.神经网络和深度学习入门知识
[Python人工智能] 五.theano实现神经网络正规化Regularization处理
[Python人工智能] 六.神经网络的评价指标、特征标准化和特征选择
[Python人工智能] 七.加速神经网络、激励函数和过拟合

参考文献:
[1] 神经网络和机器学习基础入门分享 - 作者的文章
[2] 斯坦福机器学习视频NG教授: https://class.coursera.org/ml/class/index
[3] 书籍《游戏开发中的人工智能》、《游戏编程中的人工智能技术》
[4] 网易云莫烦老师视频(强推 我付费支持老师一波): https://study.163.com/course/courseLearn.htm?courseId=1003209007
[5] Google官方卷积神经网络介绍视频 - 优达学城
[6] 用 Tensorflow 建立 CNN - 不会停的蜗牛
[7] 【深度学习系列】用PaddlePaddle和Tensorflow实现经典CNN网络GoogLeNet - Charlotte77
[8] Tensorflow实现CNN用于MNIST识别 - siucaan
[9] MNIST手写体识别任务 - chen645096127
[10] 机器学习实战—MNIST手写体数字识别 - RunningSucks
[11] https://github.com/siucaan/CNN_MNIST


Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/51642
 
589 次点击