import tensorflow as tf
import tensorflow.examples.tutorials.mnist.input_data as input_data
import random
import time
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
#使其能显示汉字
# 读取mnist数据,下载后的Mnist并解压后,放在项目的同级目录下,通过下面程序即可读取
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
batchsize=64#每一批次训练64个样本
# 在训练时,None表示从训练集中取得一张图表(x_data),及图表的值(y_data)
# 在测试评估模型时,None表示整个测试集合
x_data = tf.placeholder("float", [None, 784])
y_data = tf.placeholder("float", [None, 10])
x_image = tf.reshape(x_data, [-1, 28, 28, 1]) # 改变x_data的格式转为4维的向量[batch,in_hight,in_width,in_channels]
# 第一层卷积与最大池化
w1 = tf.Variable(tf.truncated_normal([5, 5, 1, 32], stddev=0.1)) # 卷积核大小,5 * 5的卷积核,1表示输入为灰度图,也表示输入是一维的,32个卷积核
b1 = tf.Variable(tf.constant(0.1, shape=[32]))#一个卷积核给一个偏置项,赋值为0.1
j1 = tf.nn.conv2d(x_image, w1, strides=[1, 1, 1, 1], padding="SAME")#卷积层,步长为1,padding补0
h1 = tf.nn.relu(j1 + b1)#激活函数层,经过卷积之后加上偏置项
p1 = tf.nn.max_pool(h1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")#池化层,池化窗口的大小为2 * 2,所以步长也变为2
# 第二层卷积与最大池化
w2 = tf.Variable(tf.truncated_normal([5, 5, 32, 64], stddev=0.1)) #卷积核大小,
b2 = tf.Variable(tf.constant(0.1, shape=[64]))
h2 = tf.nn.relu(tf.nn.conv2d(p1, w2, strides=[1, 1, 1, 1], padding="SAME") + b2)
p2 = tf.nn.max_pool(h2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
# 紧密连接层一
# 将第二层max-pooling的输出连接成为一个一维向量,作为该层的输入。
wf1 = tf.Variable(tf.truncated_normal([7 * 7 * 64, 1024], stddev=0.1))
bf1 = tf.Variable(tf.constant(0.1, shape=[1024]))
fc1 = tf.nn.relu(tf.matmul(tf.reshape(p2, [-1, 7 * 7 * 64]), wf1) + bf1)
keep_prob = tf.placeholder(tf.float32)
fc1_drop = tf.nn.dropout(fc1, keep_prob=keep_prob)
# 紧密连接层二
# Softmax层:输出为10,输出的每一维都是图片y属于该类别的概率。
wf2 = tf.Variable(tf.truncated_normal([1024, 10], stddev=0.1))
bf2 = tf.Variable(tf.constant(0.1, shape=[10]))
y = tf.nn.softmax(tf.matmul(fc1_drop, wf2) + bf2)
# 建立训练模型
cross_entropy = tf.square(y - y_data)#平方差损失函数
loss = tf.reduce_mean(cross_entropy)
train = tf.train.AdamOptimizer(1e-4).minimize(loss)#自适应优化器
# 建立判断正确与统计模型
correct = tf.equal(tf.argmax(y_data, 1), tf.argmax(y, 1)) # 比较训练集中的结果与计算的结果,返回TRUE
accuracy = tf.reduce_mean(tf.cast(correct, tf.float32)) # 因为correct返回为TRUE,转化为float32的1.0,对传入的整个batch求平均值,即为正确率
# 开始训练
init=tf.initialize_all_variables()
Testaccuracy=[]
testaccuracysum=0
Loss = []
with tf.Session() as sess:
sess.run(init)
start_time = time.clock()
for i in range(1,2501): # 训练次数
batch = mnist.train.next_batch(batchsize)
# 简单说一下keep_prob设置不同,在做判断与统计时,我们不做dropout,所以设1.0,但在训练时我们需要进行dropout,所以设为0.5
sess.run(train, feed_dict={x_data: batch[0], y_data: batch[1], keep_prob: 0.5})
Loss.append(sess.run(loss, feed_dict={x_data: batch[0], y_data: batch[1], keep_prob: 0.5}))
# 对测试集进行测试
if i % 500 == 0:
end_time = time.clock()
testaccuracy = sess.run(accuracy,feed_dict={x_data: mnist.test.images, y_data: mnist.test.labels, keep_prob: 1})
print("第" + str(i) + "次运算的测试集识别率为" + str(testaccuracy) + '用时:' + str(end_time - start_time) + 's')
X = []
for i in range(len(Loss)):
X.append(i)
plt.plot(X, Loss, color = 'r')
plt.title('损失函数图像')
plt.xlabel('轮数')
plt.ylabel('损失函数值')
plt.show()
最终画出的损失函数图像为: