1、何为手写数字识别问题?
手写数字识别即将如下图所示的各种各样的手写体阿拉伯数字识别出来的一个过程,这个问题已经被研究的很成熟了,也有人搜集和整理了手写数字的数据集-mnist。
2、如何解决手写数字识别问题?
在本次的手写数字识别问题中我们运用到了前面所讲的线性回归模型,通过利用多层的线性回归,并引入非线性因素relu进行训练,训练好模型后进行测试,整个模型公式如下所示:
上述公式所述的过程从直观上看就是一个如下图所示的三层神经网络 ,每一层都运用了线性回归,并运用了relu()函数作为网络中的非线性因素。在建立网络的过程中还运用到了tensorflow框架。
该三层网络输入为28*28=784个结点,输出为10个节点,这10个结点分别对应的是每一个数字的概率,通过寻找最大概率对应的结点即可分辨出该手写数字体是什么数字。
3、实战及代码
# -*- coding: utf-8 -*-
"""
Created on Thu Apr 2 08:36:14 2020
@author: lenovo
"""
import tensorflow as tf
import numpy as np
from tensorflow.keras import datasets,layers,optimizers
#step1:读入图片
(x_train, y_train), (x_test, y_test) = datasets.mnist.load_data()
print('datasets:',x_train.shape,y_train.shape,x_test.shape,y_test.shape)
#将输入数据的类型转换为tensor型
x_train=tf.convert_to_tensor(x_train,dtype=tf.float32)/255.#训练集
y_train = tf.one_hot(y_train, depth=10)
x_test=tf.convert_to_tensor(x_test,dtype=tf.float32)/255.#测试集
#建立训练集
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.batch(200)
#建立测试集
test_dataset = tf.data.Dataset.from_tensor_slices((x_test, y_test))
test_dataset = test_dataset.batch(200)
#step2:建立模型
#三层模型,1.784-512,2.512-256,3.256-10
model = tf.keras.Sequential([
layers.Dense(512, activation='relu'),
layers.Dense(256, activation='relu'),
layers.Dense(10)])
#梯度下降优化,学习率为0.0001
optimizer = optimizers.SGD(learning_rate=0.0001)
#step3:训练模型
def execute_train_epoch(epoch):
# 执行循环
for step, (x_train, y_train) in enumerate(train_dataset):
with tf.GradientTape() as tape:
# 输入矩阵变维,[b, 28, 28] => [b, 784]
x_train = tf.reshape(x_train, (-1, 28*28))
# 计算输出,[b, 784] => [b, 10]
out = model(x_train)
# 计算loss
loss = tf.reduce_sum(tf.square(out - y_train)) / x_train.shape[0]
# 更新 w1, w2, w3, b1, b2, b3
grads = tape.gradient(loss, model.trainable_variables)
# 梯度下降,w' = w - lr * grad
optimizer.apply_gradients(zip(grads, model.trainable_variables))
if step % 100 == 0:
print(epoch, step, 'loss:', loss.numpy())
#训练
def train():
for epoch in range(30):
execute_train_epoch(epoch)
#step4:执行测试
def test():
for step, (x_test, y_test) in enumerate(test_dataset):
# 输入矩阵变维,[b, 28, 28] => [b, 784]
x_test= tf.reshape(x_test, (-1, 28*28))
# 计算输出,[b, 784] => [b, 10]
out = model(x_test)
#根据计算输出结果进行数字分类
for i in range(200):
number=out[i,:]
number=np.array(number)
print('Number is:',np.argmax(number))
train()
test()
训练结果:
测试结果: