import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np
def variable_init(shape):
"""
定义一个变量初始化函数
:return:
"""
return tf.Variable(initial_value=tf.random.normal(shape=shape))
def mnist_cnn(x_train):
"""
构建卷积神经网络进行特征提取
:param x:
:return:
"""
# 先对x[None, 784]的阶数进行修改,改为四阶[None, 28, 28, 1](batch, height, width, channels)
# 注意:reshape中-1作为未知数占位符, 因为在训练集中,输入样本batch为100,而在测试集中每次输入一个样本
# 进行预测。所以如果指定了reshape中的batch大小,则会在训练完成后进行测试时出现数据格式问题。
input_x = tf.reshape(x_train, shape=[-1, 28, 28, 1])
with tf.variable_scope("conv1"):
# 卷积层1
# 设置卷积核(就是设置权重和偏置)
filter1_Weights = variable_init([5, 5, 1, 32])
filter1_bias = variable_init([32])
conv1 = tf.nn.conv2d(input=input_x, filter=filter1_Weights, strides=[1, 1, 1, 1], padding="SAME") + filter1_bias
# 激活函数:Relu
conv1_relu = tf.nn.relu(conv1)
# 池化层
conv1_pool = tf.nn.max_pool(value=conv1_relu, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
with tf.variable_scope("conv2"):
# 卷积层2
filter2_Weights = variable_init([5, 5, 32, 64])
filter2_bias = variable_init([64])
conv2 = tf.nn.conv2d(input=conv1_pool, filter=filter2_Weights, strides=[1, 1, 1, 1], padding="SAME") + filter2_bias
# 激活函数:Relu
conv2_relu = tf.nn.relu(conv2)
# 池化层
conv2_pool = tf.nn.max_pool(value=conv2_relu, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
with tf.variable_scope("fc"):
# 全连接层
# 因为要进行二阶矩阵相乘,先改变形状
fc_input = tf.reshape(conv2_pool, shape=[-1, 7*7*64])
fc_Weights = variable_init([7*7*64, 10])
fc_bias = variable_init([10])
y_predict = tf.matmul(fc_input, fc_Weights) + fc_bias
return y_predict
def mnist_recognition():
"""
使用cnn进行手写体识别
:return:
"""
# 1、准备数据
# 两种数据读取方式:
# (1)、QueueRunner
# (2)、Feeding
mnist = input_data.read_data_sets(r"E:\GameDownload\dataset_mnist", one_hot=True)
x_train = tf.placeholder(dtype=tf.float32, shape=[None, 784])
y_true = tf.placeholder(dtype=tf.float32, shape=[None, 10])
# 2、构建cnn模型(注意模型参数应用变量存储)
y_predict = mnist_cnn(x_train)
# print(y_predict)
# 3、构造损失函数(用softmax表示的交叉熵)
error = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=y_predict))
# 4、优化损失(使用梯度下降方法)
optimizer = tf.train.AdamOptimizer(learning_rate=0.02).minimize(error)
# optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(error)
# 5、计算准确率,对y_predict使用argmax可以找出其一行中最大值所在的列
# 由于使用的是one-hot编码,所以预测值与真实值在编码内的位置相同时为true,否则为false
# 之后将bool值转为浮点数后求均值,即为一个batch内true的几率
equal_list = tf.equal(tf.argmax(y_predict, 1), tf.argmax(y_true, 1))
accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32))
init = tf.global_variables_initializer()
with tf.compat.v1.Session() as sess:
sess.run(init)
# 给出一次批处理加载的图片样本个数
image, label = mnist.train.next_batch(100)
# print(x_train)
print("image_shape:", np.shape(image))
for i in range(3000):
loss, _, y_predict_val, accuracy_val = sess.run([error, optimizer, y_predict, accuracy],
feed_dict={y_true: label, x_train: image})
# print("y_predict:\n", sess.run(y_predict, feed_dict={y_true: label, x_train: image}))
# print("第%d次迭代后:损失为:%f, 准确率为%f" % (i + 1, loss, accuracy_val))
# 6、得到模型之后在测试集中进行验证
count = 0.0
for i in range(100):
x_test, y_test = mnist.test.next_batch(1)
test_predict = tf.argmax(sess.run(y_predict, feed_dict={x_train: x_test, y_true: y_test}), 1).eval()
test_true = tf.argmax(y_test, 1).eval()
if test_true == test_predict:
count += 1
print("第%d次测试的预测值为:%d, 真实值为:%d" % (i+1, test_predict, test_true))
# print("test_true:", test_true)
# print("test_predict:", sess.run(y_predict, feed_dict={x_train: x_test, y_true: y_test}))
print("在测试集上模型准确率为:%f" % (count / 100))
return None
if __name__ == "__main__":
# file_name_list = os.listdir(r"E:\GameDownload\dataset_mnist")
# # print(file_name_list)
# file_list = [os.path.join(r"E:\GameDownload\dataset_mnist", file_name)
# for file_name in file_name_list if file_name[-4:] == "byte"]
# # print(file_queue)
mnist_recognition()
用卷积神经网络进行mnist手写体识别
最新推荐文章于 2022-03-03 16:03:24 发布