经过两周学习实现了Tensorflow入门程序的编写与理解,写这篇文章对两周的学习进行总结。
目 录
一、导入数据
在数据的导入过程中,注意自己的Tensorflow的版本,需要把数据集提前下载到MNIST_data目录下。
MNIST 数据集可在 http://yann.lecun.com/exdb/mnist/ 获取, 它包含了四个部分:
- Training set images: train-images-idx3-ubyte.gz (9.9 MB, 解压后 47 MB, 包含 60,000 个样本)
- Training set labels: train-labels-idx1-ubyte.gz (29 KB, 解压后 60 KB, 包含 60,000 个标签)
- Test set images: t10k-images-idx3-ubyte.gz (1.6 MB, 解压后 7.8 MB, 包含 10,000 个样本)
- Test set labels: t10k-labels-idx1-ubyte.gz (5KB, 解压后 10 KB, 包含 10,000 个标签)
import tensorflow as tf
import numpy as np
from tensorflow.contrib.layers.python.layers import batch_norm #TensorFlow内部的批量化函数
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data",one_hot = True)
#导入MNIST数据集,从MNIST_data文件中,前提是吧数据集下载到MNIST_data文件中
二、定义函数与变量
定义权重、偏值、卷积和池化函数。解析以及附到代码处
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)
#定义权值变量 ,截断产生正态随机函数 stddev(标准差)=0.1
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)
#同上 产生一个恒定值为0.1
def conv2d(x, W):
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
#定义卷积函数tf.nn.conv2d (input, filter, strides, padding, use_cudnn_on_gpu=None, data_format=None, name=None)
#input 输入在卷积的图像(一个张量)
#filter 卷积核(一个张量) strides(卷积时每一维度的步长) padding(考虑边界)
def max_pool_2x2(x):
return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
#同上
x = tf.placeholder(tf.float32, [None, 784]) #28*28
#定义占位符,数据维度[行任意,28*28]
y_ = tf.placeholder(tf.float32, [None, 10]) #0~9十个输出
train = tf.placeholder(tf.float32)
三、定义层
对于MNIST数据的学习需要两层网络,定义两层卷积层两层池化层和两层全连接层。在卷积与池化的过程数据集维度(长宽)变小,深度变深。
第一层网络
W=【5,5,1,32】 卷积核大小为5*5,输入厚度为1,输出厚度(卷积层)32。 32是卷积层最好为2的n次方
将图片变为【-1,28,28,1】,28*28为图片像素,1为channel(灰度图片)-1可以通过其他维度自动计算
经过卷积层与池化层后,数据的维度在代码注释中可以看到
#构建网络结构,两层卷积层
W_conv1 = weight_variable([5, 5, 1, 32])
#W_conv1 维度为[5,5,1,32],5*5是卷积核,1是输入厚度,32是输出厚度
b_conv1 = bias_variable([32])
x_image = tf.reshape(x, [-1, 28, 28, 1])
#如果等于-1的话,
# 那么Numpy会根据剩下的维度计算出数组的另外一个shape属性值
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1) #28*28*32
#x,w先进行卷积,再加上+偏执b,最后通过激活函数
h_pool1 = max_pool_2x2(h_conv1)#14*14*32
#卷积后再进行池化
第二层网络
从第一层网络接收过来的数据维度为14*14*32
在经过卷积核池化后变为7*7*64
#*********第二层卷积层*************#
W_conv2 = weight_variable([5, 5, 32, 64])
#卷积核大小为5*5 输入大小为32,输出大小为64(厚度)
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2) #14*14*64
h_pool2 = max_pool_2x2(h_conv2)#7*7*64
全连接层
由于全连接层是将所有的图像所有信息都进行输出,所以要将维度进行变化为【7*7*64,1024】
tf.matmul():定义矩阵乘法
tf.nn.dropout():定义失活函数,可以减小网络的过拟合问题
tf.nn.softmax():采用指数运算,将输出值变换到0-1之间
#***********定义全连接层************#
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])
h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64])
#[n,7,7,64]→[n,7*7*64]
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
#这里用的matmul乘法,不是用conv2d
keep_prob = tf.placeholder(tf.float32)
#定义dropout层 失活神经函数
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
#*********定义第二层全连接层********#
W_fc2 = weight_variable([1024, 10])
#输入深度为1024,输出为10 0~9
b_fc2 = bias_variable([10])
y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
#Softmax的含义:Softmax简单的说就是把一个N*1的向量归一化为(0,1)之间的值,
# 由于其中采用指数运算,使得向量中数值较大的量特征更加明显。
四、定义损失函数并训练保存网络
定义交叉熵损失函数:cross_entropy
采用Adam算法进行优化
saver = tf.train.Save()
saver.save(sess,'目录')
cross_entropy =tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y_conv),
reduction_indices=[1]))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
#利用Adam优化算法
#tf.equal 返回x=y,返回Ture or false
# tf.argmax(input,axis)
# 根据axis取值的不同返回每行(1)或者每列(0)最大值的索引
correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
saver = tf.train.Saver()
#训练网络之后保存训练好的模型,以及在程序中读取已保存好的模型
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for i in range(20000):
batch = mnist.train.next_batch(100) #每次批量为100
if i % 100 == 0:
train_accuracy = accuracy.eval(feed_dict={x: batch[0], y_: batch[1], keep_prob: 1.0})
#eval() 其实就是tf.Tensor的Session.run() 的另外一种写法。 #没有失活
#第一个元素为预测标签,第二个元素为one_hot标签
print('step %d, training accuracy %g' % (i, train_accuracy)) #%g浮点数
train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})
saver.save(sess, 'WModel/model.ckpt')
#将模型存入到这个文件夹下
print('test accuracy %g' % accuracy.eval(feed_dict={x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))
结果实现
从画板中写出“5”进行测试
在进行模型保存后,可以利用电脑上的画图工具进行测试,注意:图像大小为28*28
结果如下: