源码如下:
# coding: utf-8
# 基于 LeNet5 的 MNIST 手写数字识别模型
import numpy as np
import random
#import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
# 数据集路径
data_dir='./data/mnist'
# 自动下载 MNIST 数据集
mnist = input_data.read_data_sets(data_dir, one_hot=True)
# 如果自动下载失败,则手工从官网上下载 MNIST 数据集,然后进行加载
# 下载地址 http://yann.lecun.com/exdb/mnist/
#mnist=input_data.read_data_sets(data_dir,one_hot=True)
# 提取训练集、测试集
train_xdata=mnist.train.images
test_xdata=mnist.test.images
# 提取标签数据
train_labels=mnist.train.labels
test_labels=mnist.test.labels
# 训练数据,占位符
x = tf.placeholder("float", shape=[None, 784])
# 训练的标签数据,占位符
y_ = tf.placeholder("float", shape=[None, 10])
# 将样本数据转为28x28
x_image = tf.reshape(x, [-1, 28, 28, 1])
# 保留概率,用于 dropout 层
keep_prob = tf.placeholder(tf.float32)
# 模型的相关参数
step_cnt=10000 # 训练模型的迭代次数
batch_size=100 # 每次迭代时,批量获取样本的数据量
learning_rate=0.001 # 学习率
# 模型保存路径
model_dir='./model/mnist'
# LeNet5 网络模型
def lenet_network():
# 第一层:卷积层
# 卷积核尺寸为5x5,通道数为1,深度为32,移动步长为1,采用ReLU激励函数
conv1_weights = tf.get_variable("conv1_weights", [5, 5, 1, 32], initializer=tf.truncated_normal_initializer(stddev=0.1))
conv1_biases = tf.get_variable("conv1_biases", [32], initializer=tf.constant_initializer(0.0))
conv1 = tf.nn.conv2d(x_image, conv1_weights, strides=[1, 1, 1, 1], padding='SAME')
relu1 = tf.nn.relu(tf.nn.bias_add(conv1, conv1_biases))
# 第二层:最大池化层
# 池化核的尺寸为2x2,移动步长为2,使用全0填充
pool1 = tf.nn.max_pool(relu1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
# 第三层:卷积层
# 卷积核尺寸为5x5,通道数为32,深度为64,移动步长为1,采用ReLU激励函数
conv2_weights = tf.get_variable("conv2_weights", [5, 5, 32, 64], initializer=tf.truncated_normal_initializer(stddev=0.1))
conv2_biases = tf.get_variable("conv2_biases", [64], initializer=tf.constant_initializer(0.0))
conv2 = tf.nn.conv2d(pool1, conv2_weights, strides=[1, 1, 1, 1], padding='SAME')
relu2 = tf.nn.relu(tf.nn.bias_add(conv2, conv2_biases))
# 第四层:最大池化层
# 池化核尺寸为2x2, 移动步长为2,使用全0填充
pool2 = tf.nn.max_pool(relu2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
# 第五层:全连接层
fc1_weights = tf.get_variable("fc1_weights", [7 * 7 * 64, 1024],
initializer=tf.truncated_normal_initializer(stddev=0.1))
fc1_baises = tf.get_variable("fc1_baises", [1024], initializer=tf.constant_initializer(0.1))
pool2_vector = tf.reshape(pool2, [-1, 7 * 7 * 64])
fc1 = tf.nn.relu(tf.matmul(pool2_vector, fc1_weights) + fc1_baises)
# Dropout层(即按keep_prob的概率保留数据,其它丢弃),以防止过拟合
fc1_dropout = tf.nn.dropout(fc1, keep_prob)
# 第六层:全连接层
fc2_weights = tf.get_variable("fc2_weights", [1024, 10],
initializer=tf.truncated_normal_initializer(stddev=0.1)) # 神经元节点数1024, 分类节点10
fc2_biases = tf.get_variable("fc2_biases", [10], initializer=tf.constant_initializer(0.1))
fc2 = tf.matmul(fc1_dropout, fc2_weights) + fc2_biases
# 第七层:输出层
y_conv = tf.nn.softmax(fc2)
return y_conv
# 训练模型
def train_model():
# 加载 LeNet5 网络结构
y_conv=lenet_network()
# 定义交叉熵损失函数
# y_ 为真实标签
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y_conv), reduction_indices=[1]))
# 选择优化器,使优化器最小化损失函数
train_step = tf.train.AdamOptimizer(learning_rate).minimize(cross_entropy)
# 返回模型预测的最大概率的结果,并与真实值作比较
correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))
# 用平均值来统计测试准确率
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
# 训练模型
saver=tf.train.Saver()
with tf.Session() as sess:
tf.global_variables_initializer().run()
for step in range(step_cnt):
batch = mnist.train.next_batch(batch_size)
if step % 100 == 0:
# 每迭代100步进行一次评估,输出结果,保存模型,便于及时了解模型训练进展
train_accuracy = accuracy.eval(feed_dict={x: batch[0], y_: batch[1], keep_prob: 1.0})
print("step %d, training accuracy %g" % (step, train_accuracy))
saver.save(sess,model_dir+'/my_mnist_model.ctpk',global_step=step)
train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.8})
# 使用测试数据测试准确率
test_acc=accuracy.eval(feed_dict={x: test_xdata, y_: test_labels, keep_prob: 1.0})
print("test accuracy %g" %test_acc)
# 模型测试应用
def test_model():
# 加载 LeNet5 网络结构
y_conv = lenet_network()
# 加载 MNIST 模型
saver = tf.train.Saver()
with tf.Session() as sess:
saver.restore(sess, tf.train.latest_checkpoint(model_dir))
# 随机提取 MNIST 测试集的一个样本数据和标签
test_len=len(mnist.test.images)
test_idx=random.randint(0,test_len-1)
x_image=mnist.test.images[test_idx]
y=np.argmax(mnist.test.labels[test_idx])
# 跑模型进行识别
y_conv = tf.argmax(y_conv,1)
pred=sess.run(y_conv,feed_dict={x:[x_image], keep_prob: 1.0})
print('正确:',y,',预测:',pred[0])
if __name__ == "__main__":
# 训练模型
train_model()
# 测试应用模型
#test_model()