前面我们曾有篇文章中提到过关于用tensorflow训练手写2828像素点的数字的识别,在那篇文章中我们把手写数字图像直接碾压成了一个784列的数据进行识别,但实际上,这个图像是2828长宽结构的,我们这次使用CNN卷积神经网络来进行识别。

卷积神经网络我的理解是部分模仿了人眼的功能。

我们在看一个图像时不是一个像素点一个像素点去分辨的,我们的眼睛天然地具有大局观,我们看到某个图像时自动地会把其中的细节部分给聚合起来进行识别,相反,如果我们用个放大镜看到其中的各个像素点时反而不知道这是啥东西了。

因此卷积神经网络就把每个像素点的图像进行一定程度上的模糊化,而怎么进行模糊化呢?它是通过选择一小片的区域范围,把这小片中的图像数据缩小其长宽,但增加其高度值。然后进行某种计算,最终达到有点类似模糊化图像的目的,但这个模糊化的图像中反而能够比较容易识别出相应的边界及形状。

具体大家可以到网上搜索相关的理论知识,这里不细讲,只专注于如何在tensorflow中实现 CNN的功能。

之前在tensorflow分类-【老鱼学tensorflow】中已经用一般的神经网络进行过手写数字的识别,我们在那个程序的基础上来进行,那篇文章的地址为:http://www.cnblogs.com/dreampursuer/p/8026866.html

import tensorflow as tf

# 准备数据
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('D:/todel/python/MNIST_data/', one_hot=True) def add_layer(inputs, in_size, out_size, activation_function=None):
"""
添加层
:param inputs: 输入数据
:param in_size: 输入数据的列数
:param out_size: 输出数据的列数
:param activation_function: 激励函数
:return:
""" # 定义权重,初始时使用随机变量,可以简单理解为在进行梯度下降时的随机初始点,这个随机初始点要比0值好,因为如果是0值的话,反复计算就一直是固定在0中,导致可能下降不到其它位置去。
Weights = tf.Variable(tf.random_normal([in_size, out_size]))
# 偏置shape为1行out_size列
biases = tf.Variable(tf.zeros([1, out_size]) + 0.1)
# 建立神经网络线性公式:inputs * Weights + biases,我们大脑中的神经元的传递基本上也是类似这样的线性公式,这里的权重就是每个神经元传递某信号的强弱系数,偏置值是指这个神经元的原先所拥有的电位高低值
Wx_plus_b = tf.matmul(inputs, Weights) + biases
if activation_function is None:
# 如果没有设置激活函数,则直接就把当前信号原封不动地传递出去
outputs = Wx_plus_b
else:
# 如果设置了激活函数,则会由此激活函数来对信号进行传递或抑制
outputs = activation_function(Wx_plus_b)
return outputs # 定义输入数据
xs = tf.placeholder(tf.float32, [None, 28*28])
ys = tf.placeholder(tf.float32, [None, 10]) #10列,就是那个one hot结构的数据 # 定义层,输入为xs,其有28*28列,输出为10列one hot结构的数据,激励函数为softmax,对于one hot类型的数据,一般激励函数就使用softmax
prediction = add_layer(xs, 28*28, 10, activation_function=tf.nn.softmax) # 定义loss值
cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction), axis=1))
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy) sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init) def computer_accuracy(v_xs, v_ys):
"""
计算准确度
:param v_xs:
:param v_ys:
:return:
"""
# predication是从外部获得的变量
global prediction
# 根据小批量输入的值计算预测值
y_pre = sess.run(prediction, feed_dict={xs:v_xs})
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})
return result for i in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(100)
sess.run(train_step, feed_dict={xs: batch_xs, ys: batch_ys})
if i % 50 == 0:
# 每隔50条打印一下预测的准确率
print(computer_accuracy(mnist.test.images, mnist.test.labels))

添加必要的函数

生成权重变量

# 生成权重变量
def weight_variable(shape):
# 产生一个随机变量
init = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(init)

定义bias变量

# 定义bias变量
def bias_variable(shape):
# bias的初始值比权重值稍微简单点,直接用非0常量定义就可以
init = tf.constant(0.1, shape=shape)
return tf.Variable(init)

定义卷积神经网络层

# 定义卷积神经网络层
def conv2d(x, W):
# strides:结构为[1, x方向上的步长,y方向上的步长, 1],这里x方向上的步长和y方向上的步长都设置为1
# padding可选值有VALID和SAME,VALID方式会在边界处比原始图片小一点,而SAME方式会在边界处用0来补充,从而保持跟原始图相同的大小
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

定义pooling

# 为了防止跨步太大丢失掉信息,我们会在中间建立一个pooling,使其跨度减小,但在pooling时跨度可以变大一点,这样在最后的图片生成时可以把大小减小下来但同时又尽可能保存了相关的信息
def max_pool_2x2(x):
# strides结构依然为:[1, x方向上的步长,y方向上的步长, 1],这里x方向上的步长和y方向上的步长都设置为2,这样在pool时把图像的大小给减小了
return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

编写主程序部分

定义输入数据

# 定义输入数据
xs = tf.placeholder(tf.float32, [None, 28*28])
ys = tf.placeholder(tf.float32, [None, 10]) #10列,就是那个one hot结构的数据
keep_prob = tf.placeholder(tf.float32)
# 为了使用卷积神经网络,我们需要把原始的一维的数据变换成长宽表示的平面图的数据,把xs的形状变成[-1,28,28,1],-1代表先不考虑输入的图片例子多少这个维度,
# 后面的1是channel的数量,因为我们输入的图片是黑白的,因此channel是1,例如如果是RGB图像,那么channel就是3。
x_image = tf.reshape(xs, [-1, 28, 28, 1])

定义卷积层1

# 定义卷积层1,以5*5的面积进行扫描,因为黑白图片channel是1所以输入是1,输出是32个高度的值
W_conv1 = weight_variable([5, 5, 1, 32])
# bias的大小是32个长度,因此我们传入它的shape为[32]
b_conv1 = bias_variable([32])
# 定义好了Weight和bias,我们就可以定义卷积神经网络的第一个卷积层h_conv1=conv2d(x_image,W_conv1)+b_conv1,同时我们对h_conv1进行非线性处理,
# 也就是激活函数来处理喽,这里我们用的是tf.nn.relu(修正线性单元)来处理,要注意的是,因为采用了SAME的padding方式,输出图片的大小没有变化依然是28x28,
# 只是厚度变厚了,因此现在的输出大小就变成了28x28x32
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
# 最后我们再进行pooling的处理就ok啦,经过pooling的处理,输出大小就变为了14x14x32
h_pool1 = max_pool_2x2(h_conv1)

定义卷积层2

# 定义卷积层2
# 扫描的面积还是定义成5*5,输入大小为32,因为卷积层1中输出为32就被设置为这里的输入大小了。输出大小设定为64,也就是变得更高了
W_conv2 = weight_variable([5, 5, 32, 64])
# bias的大小是64个长度,因此我们传入它的shape为[64]
b_conv2 = bias_variable([64])
# 定义好了Weight和bias,我们就可以定义卷积神经网络的第二个卷积层h_conv2=conv2d(h_pool1,W_conv2)+b_conv2,同时我们对h_conv2进行非线性处理,
# 也就是激活函数来处理喽,这里我们用的是tf.nn.relu(修正线性单元)来处理,要注意的是,因为采用了SAME的padding方式,输出图片的大小没有变化依然是在第一层卷集层输出时的14*14,
# 只是厚度变厚了,因此现在的输出大小就变成了14x14x64
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
# 最后我们再进行pooling的处理就ok啦,经过pooling的处理,输出大小就变为了7x7x64
h_pool2 = max_pool_2x2(h_conv2)

定义神经网络全连接层1

# 定义神经网络全连接层1
# 其形状为h_pool2的输出形状7*7*64,输出为1024个神经元
W_fc1 = weight_variable([7*7*64, 1024])
b_fc1 = bias_variable([1024])
# 把h_pool2的输出的包含长宽平面的信息形状转换成一个维度的数据,相当于变平的操作:[n_samples, 7, 7, 64] => [n_samples, 7*7*64]
h_pool1_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool1_flat, W_fc1) + b_fc1)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

定义神经网络全连接层2

# 定义神经网络全连接层2
# 其输入为全连接层1的输出1024,输出为0-9数字的one hot格式,因此为10列
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
prediction = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

定义loss值

# 定义loss值
cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction), axis=1))
# 对于比较庞大的系统可以用AdamOptimizer比较好一点
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
# train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

执行

sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init) for i in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(100)
sess.run(train_step, feed_dict={xs: batch_xs, ys: batch_ys, keep_prob: 0.5})
if i % 50 == 0:
# 每隔50条打印一下预测的准确率
print(computer_accuracy(mnist.test.images, mnist.test.labels))

全部代码

import tensorflow as tf

def add_layer(inputs, in_size, out_size, activation_function=None):
"""
添加层
:param inputs: 输入数据
:param in_size: 输入数据的列数
:param out_size: 输出数据的列数
:param activation_function: 激励函数
:return:
""" # 定义权重,初始时使用随机变量,可以简单理解为在进行梯度下降时的随机初始点,这个随机初始点要比0值好,因为如果是0值的话,反复计算就一直是固定在0中,导致可能下降不到其它位置去。
Weights = tf.Variable(tf.random_normal([in_size, out_size]))
# 偏置shape为1行out_size列
biases = tf.Variable(tf.zeros([1, out_size]) + 0.1)
# 建立神经网络线性公式:inputs * Weights + biases,我们大脑中的神经元的传递基本上也是类似这样的线性公式,这里的权重就是每个神经元传递某信号的强弱系数,偏置值是指这个神经元的原先所拥有的电位高低值
Wx_plus_b = tf.matmul(inputs, Weights) + biases
if activation_function is None:
# 如果没有设置激活函数,则直接就把当前信号原封不动地传递出去
outputs = Wx_plus_b
else:
# 如果设置了激活函数,则会由此激活函数来对信号进行传递或抑制
outputs = activation_function(Wx_plus_b)
return outputs def computer_accuracy(v_xs, v_ys):
"""
计算准确度
:param v_xs:
:param v_ys:
:return:
"""
# predication是从外部获得的变量
global prediction
# 根据小批量输入的值计算预测值
y_pre = sess.run(prediction, feed_dict={xs:v_xs, keep_prob: 1})
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 # 生成权重变量
def weight_variable(shape):
# 产生一个随机变量
init = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(init) # 定义bias变量
def bias_variable(shape):
# bias的初始值比权重值稍微简单点,直接用非0常量定义就可以
init = tf.constant(0.1, shape=shape)
return tf.Variable(init) # 定义卷积神经网络层
def conv2d(x, W):
# strides:结构为[1, x方向上的步长,y方向上的步长, 1],这里x方向上的步长和y方向上的步长都设置为1
# padding可选值有VALID和SAME,VALID方式会在边界处比原始图片小一点,而SAME方式会在边界处用0来补充,从而保持跟原始图相同的大小
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME') # 为了防止跨步太大丢失掉信息,我们会在中间建立一个pooling,使其跨度减小,但在pooling时跨度可以变大一点,这样在最后的图片生成时可以把大小减小下来但同时又尽可能保存了相关的信息
def max_pool_2x2(x):
# strides结构依然为:[1, x方向上的步长,y方向上的步长, 1],这里x方向上的步长和y方向上的步长都设置为2,这样在pool时把图像的大小给减小了
return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') # 准备数据
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('D:/todel/python/MNIST_data/', one_hot=True) # 定义输入数据
xs = tf.placeholder(tf.float32, [None, 28*28])
ys = tf.placeholder(tf.float32, [None, 10]) #10列,就是那个one hot结构的数据
keep_prob = tf.placeholder(tf.float32)
# 为了使用卷积神经网络,我们需要把原始的一维的数据变换成长宽表示的平面图的数据,把xs的形状变成[-1,28,28,1],-1代表先不考虑输入的图片例子多少这个维度,
# 后面的1是channel的数量,因为我们输入的图片是黑白的,因此channel是1,例如如果是RGB图像,那么channel就是3。
x_image = tf.reshape(xs, [-1, 28, 28, 1]) # 定义卷积层1,以5*5的面积进行扫描,因为黑白图片channel是1所以输入是1,输出是32个高度的值
W_conv1 = weight_variable([5, 5, 1, 32])
# bias的大小是32个长度,因此我们传入它的shape为[32]
b_conv1 = bias_variable([32])
# 定义好了Weight和bias,我们就可以定义卷积神经网络的第一个卷积层h_conv1=conv2d(x_image,W_conv1)+b_conv1,同时我们对h_conv1进行非线性处理,
# 也就是激活函数来处理喽,这里我们用的是tf.nn.relu(修正线性单元)来处理,要注意的是,因为采用了SAME的padding方式,输出图片的大小没有变化依然是28x28,
# 只是厚度变厚了,因此现在的输出大小就变成了28x28x32
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
# 最后我们再进行pooling的处理就ok啦,经过pooling的处理,输出大小就变为了14x14x32
h_pool1 = max_pool_2x2(h_conv1) # 定义卷积层2
# 扫描的面积还是定义成5*5,输入大小为32,因为卷积层1中输出为32就被设置为这里的输入大小了。输出大小设定为64,也就是变得更高了
W_conv2 = weight_variable([5, 5, 32, 64])
# bias的大小是64个长度,因此我们传入它的shape为[64]
b_conv2 = bias_variable([64])
# 定义好了Weight和bias,我们就可以定义卷积神经网络的第二个卷积层h_conv2=conv2d(h_pool1,W_conv2)+b_conv2,同时我们对h_conv2进行非线性处理,
# 也就是激活函数来处理喽,这里我们用的是tf.nn.relu(修正线性单元)来处理,要注意的是,因为采用了SAME的padding方式,输出图片的大小没有变化依然是在第一层卷集层输出时的14*14,
# 只是厚度变厚了,因此现在的输出大小就变成了14x14x64
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
# 最后我们再进行pooling的处理就ok啦,经过pooling的处理,输出大小就变为了7x7x64
h_pool2 = max_pool_2x2(h_conv2) # 定义神经网络全连接层1
# 其形状为h_pool2的输出形状7*7*64,输出为1024个神经元
W_fc1 = weight_variable([7*7*64, 1024])
b_fc1 = bias_variable([1024])
# 把h_pool2的输出的包含长宽平面的信息形状转换成一个维度的数据,相当于变平的操作:[n_samples, 7, 7, 64] => [n_samples, 7*7*64]
h_pool1_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool1_flat, W_fc1) + b_fc1)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob) # 定义神经网络全连接层2
# 其输入为全连接层1的输出1024,输出为0-9数字的one hot格式,因此为10列
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
prediction = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2) # 定义loss值
cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction), axis=1))
# 对于比较庞大的系统可以用AdamOptimizer比较好一点
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
# train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy) sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init) for i in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(100)
sess.run(train_step, feed_dict={xs: batch_xs, ys: batch_ys, keep_prob: 0.5})
if i % 50 == 0:
# 每隔50条打印一下预测的准确率
print(computer_accuracy(mnist.test.images, mnist.test.labels))

输出为:

0.0853
0.7785
0.8835
0.9084
0.9241
0.9316
0.9412
0.9463
0.9485
0.951
0.9561
0.9578
0.9599
0.9611
0.964
0.9644
0.966
0.9673
0.9687
0.9685

这次用卷积神经网络把结果提高了很多。

tensorflow卷积神经网络-【老鱼学tensorflow】的更多相关文章

  1. tensorflow分类-【老鱼学tensorflow】

    前面我们学习过回归问题,比如对于房价的预测,因为其预测值是个连续的值,因此属于回归问题. 但还有一类问题属于分类的问题,比如我们根据一张图片来辨别它是一只猫还是一只狗.某篇文章的内容是属于体育新闻还是 ...

  2. tensorflow例子-【老鱼学tensorflow】

    本节主要用一个例子来讲述一下基本的tensorflow用法. 在这个例子中,我们首先伪造一些线性数据点,其实这些数据中本身就隐藏了一些规律,但我们假装不知道是什么规律,然后想通过神经网络来揭示这个规律 ...

  3. tensorflow安装-【老鱼学tensorflow】

    TensorFlow是谷歌基于DistBelief进行研发的第二代人工智能学习系统,其命名来源于本身的运行原理.Tensor(张量)意味着N维数组,Flow(流)意味着基于数据流图的计算,Tensor ...

  4. tensorflow变量-【老鱼学tensorflow】

    在程序中定义变量很简单,只要定义一个变量名就可以,但是tensorflow有点类似在另外一个世界,因此需要通过当前的世界中跟tensorlfow的世界中进行通讯,来告诉tensorflow的世界中定义 ...

  5. tensorflow激励函数-【老鱼学tensorflow】

    当我们回到家,如果家里有异样,我们能够很快就会发现家中的异样,那是因为这些异常的摆设在我们的大脑中会产生较强的脑电波. 当我们听到某个单词,我们大脑中跟这个单词相关的神经元会异常兴奋,而同这个单词无关 ...

  6. tensorflow RNN循环神经网络 (分类例子)-【老鱼学tensorflow】

    之前我们学习过用CNN(卷积神经网络)来识别手写字,在CNN中是把图片看成了二维矩阵,然后在二维矩阵中堆叠高度值来进行识别. 而在RNN中增添了时间的维度,因为我们会发现有些图片或者语言或语音等会在时 ...

  7. tensorflow Tensorboard可视化-【老鱼学tensorflow】

    tensorflow自带了可视化的工具:Tensorboard.有了这个可视化工具,可以让我们在调整各项参数时有了可视化的依据. 本次我们先用Tensorboard来可视化Tensorflow的结构. ...

  8. tensorflow建造神经网络-【老鱼学tensorflow】

    上次我们添加了一个add_layer函数,这次就要创建一个神经网络来预测/拟合相应的数据. 下面我们先来创建一下虚拟的数据,这个数据为二次曲线数据,但同时增加了一些噪点,其图像为: 相应的创建这些伪造 ...

  9. tensorflow用dropout解决over fitting-【老鱼学tensorflow】

    在机器学习中可能会存在过拟合的问题,表现为在训练集上表现很好,但在测试集中表现不如训练集中的那么好. 图中黑色曲线是正常模型,绿色曲线就是overfitting模型.尽管绿色曲线很精确的区分了所有的训 ...

随机推荐

  1. antd Tree组件中,自定义右键菜单

    最近项目中,有一个需求是自定义antd的Tree组件的右键菜单功能. 直接上代码 class Demo extends Component { state = { rightClickNodeTree ...

  2. (二叉树 递归) leetcode 889. Construct Binary Tree from Preorder and Postorder Traversal

    Return any binary tree that matches the given preorder and postorder traversals. Values in the trave ...

  3. (十一) UVC调节亮度

    目录 UVC调节亮度 引入 硬件协议速览 代码框架 属性初始化 属性支持查询 具体属性值获取 具体属性值设置 代码实现 title: UVC调节亮度 date: 2019/4/23 20:30:00 ...

  4. DNS Tunnel隧道隐蔽通信实验 && 尝试复现特征向量化思维方式检测

    1. DNS隧道简介 DNS隧道技术是指利用 DNS协议建立隐蔽信 道,实现隐蔽数据传输.最早是在2004年 DanKaminsky 在 Defcon大会上发布的基于 NSTX 的 DNS隐蔽 隧道工 ...

  5. Apicloud学习第四天

    apicloud存储机制,添加和获取存储的数据 $api.setStorage('currentCity', cityList[i_]); $api.getStorage('currentCity') ...

  6. python中__str__与__repr__的区别

    __str__和repr __str__和__repr__都是python的内置方法,都用与将对象的属性转化成人类容易识别的信息,他们有什么区别呢 来看一段代码 from math import hy ...

  7. python的多线程

    1.多线程的例子 import threading #首先导入threading模块,这是使用多线程的前提 from time import ctime,sleep def music(func): ...

  8. Linux命令--tree

    目录 tree 最常用 带颜色显示2级目录 排除显示某个目录 tree tree -C :颜色显示 tree -f : 显示文件全路径 tree -L 2 :只显示2层 tree -P *.pl :只 ...

  9. ES7的async/await

    async 表示这是一个async函数,await只能用在这个函数里面. await 表示在这里等待promise返回结果了,再继续执行. await 后面跟着的应该是一个promise对象 awai ...

  10. 双目立体匹配——归一化互相关(NCC)

    归一化相关性,normalization cross-correlation,因此简称NCC,下文中笔者将用NCC来代替这冗长的名称. NCC,顾名思义,就是用于归一化待匹配目标之间的相关程度,注意这 ...