一、加载MNIST数据
TensorFlow已经准备了一个脚本来自动下载和导入MNIST数据集。它会自动创建一个'MNIST_data'的目录来存储数据。
import tensorflow as tf
import numpy as np
import random
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data',one_hot=True)
# one_hot介绍 :https://blog.csdn.net/lanhaier0591/article/details/78702558
复制代码
这里,mnist是一个轻量级的类。它以Numpy数组的形式存储着训练、校验和测试数据集。同时提供了一个函数,用于在迭代中获得minibatch,后面我们将会用到。
原文链接:http://www.tensorfly.cn/tfdoc/tutorials/mnist_download.html
二、输入与占位符
placeholder_inputs()函数将生成两个tf.placeholder操作,定义传入图表中的shape参数,shape参数中包括batch_size值,后续还会将实际的训练用例传入图表。
imageInput = tf.placeholder(tf.float32,[None,784])
# 训练图像
labeInput = tf.placeholder(tf.float32,[None,10])
# 训练标签
复制代码
三、构建一个多层卷积网络
1、权重初始化
reshape(tensor, shape, name=None)
参数
- tensor,被调整维度的张量
- shape,要调整为的形状
imageInputReshape = tf.reshape(imageInput,[-1,28,28,1])
# 2维转变为4维
复制代码
tf.truncated_normal(shape, mean, stddev)
参数
- shape表示生成张量的维度,
- mean是均值,
- stddev是标准差。
w0 = tf.Variable(tf.truncated_normal([5,5,1,32],stddev = 0.1))
# 求标准差
b0 = tf.Variable(tf.constant(0.1,shape=[32]))
# 生成一个32维的张量
复制代码
2、激励函数+卷积运算
tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, name=None)
参数
- input:指需要做卷积的输入图像,它要求是一个Tensor,具有[batch, in_height, in_width, in_channels]这样的shape,具体含义是[训练时一个batch的图片数量, 图片高度, 图片宽度, 图像通道数],注意这是一个4维的Tensor,要求类型为float32和float64其中之一
- filter:相当于CNN中的卷积核,它要求是一个Tensor,具有[filter_height, filter_width, in_channels, out_channels]这样的shape,具体含义是[卷积核的高度,卷积核的宽度,图像通道数,卷积核个数],要求类型与参数input相同,有一个地方需要注意,第三维in_channels,就是参数input的第四维
- strides:卷积时在图像每一维的步长,这是一个一维的向量,长度4
- padding:string类型的量,只能是"SAME","VALID"其中之一,这个值决定了不同的卷积方式
- use_cudnn_on_gpu:bool类型,是否使用cudnn加速,默认为true
输出:
- 结果返回一个Tensor,这个输出,就是我们常说的feature map,shape仍然是[batch, height, width, channels]这种形式。
tf.nn.max_pool(value, ksize, strides, padding, name=None)
参数
- value:池化的输入,一般池化层接在卷积层的后面,所以输出通常为feature map。feature map依旧是[batch, in_height, in_width, in_channels]这样的参数。
- ksize:池化窗口的大小,参数为四维向量,通常取[1, height, width, 1],因为我们不想在batch和channels上做池化,所以这两个维度设为了1。ps:估计面tf.nn.conv2d中stries的四个取值也有 相同的意思。
- stries:步长,同样是一个四维向量。
- padding:填充方式同样只有两种不重复了。
layer1 = tf.nn.relu(tf.nn.conv2d(imageInputReshape,w0,strides=[1,1,1,1],padding='SAME')+b0)
# layer1:激励函数+卷积运算
# imageInputReshape : M*28*28*1 w0:5,5,1,32
# layer1:M*28*28*32
复制代码
3、池化
layer1_pool = tf.nn.max_pool(layer1,ksize=[1,4,4,1],strides=[1,4,4,1],padding='SAME')
# pool采样:数据量减少很多M*28*28*32 => M*7*7*32
复制代码
4、激励函数+乘加运算
# layer2 out : softmax(激励函数 + 乘加运算)
w1 = tf.Variable(tf.truncated_normal([7*7*32,1024],stddev=0.1))
b1 = tf.Variable(tf.constant(0.1,shape=[1024]))
h_reshape = tf.reshape(layer1_pool,[-1,7*7*32])
h1 = tf.nn.relu(tf.matmul(h_reshape,w1)+b1)
# [N*7*7*32] [7*7*32,1024] = N*1024
复制代码
5、输出层
最后,我们添加一个softmax层
w2 = tf.Variable(tf.truncated_normal([1024,10],stddev=0.1))
b2 = tf.Variable(tf.constant(0.1,shape=[10]))
pred = tf.nn.softmax(tf.matmul(h1,w2)+b2)
# N*1024 1024*10 = N*10
复制代码
6、损失函数
loss0 = labeInput*tf.log(pred)
loss1 = 0
for m in range(0,500):
for n in range(0,10):
loss1 = loss1 - loss0[m,n]
loss = loss1/500
复制代码
7、训练和评估模型
train = tf.train.GradientDescentOptimizer(0.01).minimize(loss)
# 让误差尽可能缩小
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for i in range(100):
images,labels = mnist.train.next_batch(500)
sess.run(train,feed_dict={imageInput:images,labeInput:labels})
pred_test = sess.run(pred,feed_dict={imageInput:mnist.test.images,labeInput:labels})
acc = tf.equal(tf.arg_max(pred_test,1),tf.arg_max(mnist.test.labels,1))
acc_float = tf.reduce_mean(tf.cast(acc,tf.float32))
acc_result = sess.run(acc_float,feed_dict={imageInput:mnist.test.images,labeInput:mnist.test.labels})
print(acc_result)
复制代码