话不多说,下面是源码,参考了网上找的资料.模型结构:输入->h1->h2->h3->输出,尽管在mnist测试准确率达到95%,但实际使用画图程序手写10个数字进行识别, 最多只能识别出7个,跟你笔画粗细,数字是否居中,数字大小都有关系
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import datasets
# 加载mnist数据集
(x_train, y_train), (x_test, y_test) = datasets.mnist.load_data()
# 对数据进行预处理
def preprocess(x, y):
# 将x映射到[0,1]范围内
x = tf.cast(x, dtype=tf.float32) / 255.
y = tf.cast(y, dtype=tf.int32)
return (x, y)
# 构建dataset对象,对数据进行打乱,批处理等操作
train_data = tf.data.Dataset.from_tensor_slices(
(x_train, y_train)).shuffle(10000).batch(512)
train_data = train_data.map(preprocess)
test_data = tf.data.Dataset.from_tensor_slices(
(x_test, y_test)).shuffle(1000).batch(512)
test_data = test_data.map(preprocess)
# 建立权重和偏置,学习效率等训练中用到的变量
w1 = tf.Variable(tf.random.truncated_normal([28*28, 256], stddev=0.1))
b1 = tf.Variable(tf.zeros(256))
w2 = tf.Variable(tf.random.truncated_normal([256, 128], stddev=0.1))
b2 = tf.Variable(tf.zeros(128))
w3 = tf.Variable(tf.random.truncated_normal([128, 64], stddev=0.1))
b3 = tf.Variable(tf.zeros(64))
w4 = tf.Variable(tf.random.truncated_normal([64, 10], stddev=0.1))
b4 = tf.Variable(tf.zeros(10))
lr = 0.1
# 循环迭代训练
for epoch in range(100):
for step, (x, y) in enumerate(train_data):
# 数据打平
x = tf.reshape(x, [-1, 28*28])
# 构建模型并计算梯度,向前计算的过程需要在GradientTape()环境下,利用gradient()方法自动求解参数梯度并利用optimizers对象更新参数
with tf.GradientTape() as tape:
h1 = tf.nn.relu(tf.matmul(x, w1) +
tf.broadcast_to(b1, [x.shape[0], 256]))
h2 = tf.nn.relu(tf.matmul(h1, w2) + b2)
h3 = tf.nn.relu(tf.matmul(h2, w3) + b3)
out = tf.matmul(h3, w4) + b4
# 将标签one_hot编码化
y_onehot = tf.one_hot(y, depth=10)
loss = tf.reduce_mean(tf.square(out - y_onehot))
# 更新本次迭代的梯度参数
grad = tape.gradient(loss, [w1, b1, w2, b2, w3, b3, w4, b4])
w1.assign_sub(lr*grad[0])
b1.assign_sub(lr*grad[1])
w2.assign_sub(lr*grad[2])
b2.assign_sub(lr*grad[3])
w3.assign_sub(lr*grad[4])
b3.assign_sub(lr*grad[5])
w4.assign_sub(lr*grad[6])
b4.assign_sub(lr*grad[7])
# 每进行100step,打印一次训练成果
if step % 100 == 0:
print('epoch:', epoch, 'step:', step, 'loss:', float(loss))
# 每训练完一次,测试一次准确率
total_num, total_correct = 0, 0
for step, (x, y) in enumerate(test_data):
# 数据打平
x = tf.reshape(x, [-1, 28*28])
h1 = tf.nn.relu(tf.matmul(x, w1) + b1)
h2 = tf.nn.relu(tf.matmul(h1, w2) + b2)
h3 = tf.nn.relu(tf.matmul(h2, w3) + b3)
out = tf.matmul(h3, w4) + b4
# 将输出映射到[0,1]范围内
out = tf.nn.softmax(out, axis=1)
# 获取概率最大值的索引即为对应的数字
index = tf.argmax(out, axis=1)
index = tf.cast(index, dtype=tf.int32)
# 同标签进行比较以判断对错
correct = tf.cast(tf.equal(index, y), dtype=tf.int32)
correct = tf.reduce_sum(correct)
total_correct += correct
total_num += x.shape[0]
print('acc:', float(total_correct / total_num))
# 测试手写数字
for i in range(10):
path = "D:\\code_project\\vscode_python\\tensorflow_v2\\my_num\\"
path = path + str(i) + '.jpg'
img = tf.io.read_file(path)
img = tf.image.decode_jpeg(img)
img = tf.image.resize(img, [28, 28])
img = tf.image.rgb_to_grayscale(img)
x = tf.reshape(img, [1, 28*28])
x = tf.cast(x, dtype=tf.float32) / 255.
h1 = tf.nn.relu(tf.matmul(x, w1) + b1)
h2 = tf.nn.relu(tf.matmul(h1, w2) + b2)
h3 = tf.nn.relu(tf.matmul(h2, w3) + b3)
out = tf.nn.softmax(tf.matmul(h3, w4) + b4, axis=1)
index = tf.cast(tf.argmax(out, axis=1), dtype=tf.int32)
print(path, int(index[0]))