通过多层感知机实现MNIST手写体识别

1.问题描述

        通过MNIST内含有60000个数据进行训练的图像(train),图片为28*28的像素矩阵,并定义一个三层的多层感知机。经过训练,最终可以对测试的数字图像又较为准确的识别。

2.数据导入

        由于要用到MNIST中的图像,我可以利用keras.datasets直接导入MNIST中的数据,包括输入集和输出集。

import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
(train_image, train_labels), (test_image, test_labels) = tf.keras.datasets.mnist.load_data()

3.图像处理

        首先对图像增加通道维度。输入的训练图像(train)和测试图像(test)可以看作是四维的,训练的图像可看作([60000,28,28,1])。之后要对训练图像和测试图像进行归一化处理,目的是将图片中的这些值缩小到0和1之间,方便其送到神经网络模型之中。因此我们首先将这些图像组件的数据类型从整型转为浮点型,然后除以255,从而更方便接下来的训练。图像处理的代码如图所示:

train_image = tf.expand_dims(train_image, -1)
test_image = tf.expand_dims(test_image, -1)
train_image = tf.cast(train_image/255, tf.float32)
test_image = tf.cast(test_image/255, tf.float32)
train_labels = tf.cast(train_labels, tf.int64)
test_labels = tf.cast(test_labels, tf.int64)
dataset = tf.data.Dataset.from_tensor_slices((train_image, train_labels)).shuffle(60000).batch(256)
test_dataset = tf.data.Dataset.from_tensor_slices((test_image, test_labels)).batch(256)

4.创建模型(MLP多层感知机)

        首先利用sequential函数建立神经网络模型。需要学习和识别的图片的大小为28*28,并用flatten函数将其展位一维的数组,为输入层。接下来是两个隐藏层,通过dense函数实现。Dense函数内的units设置了该隐层的节点个数,令两个隐藏层的节点个数都为100。此外,dense中还利用activation激活了relu函数。对于进入神经元的来自上一层神经网络的输入向量x,使用relu函数的神经元会输出至下一层神经元或作为整个神经网络的输出(取决现神经元在网络结构中所处位置)。相较于其他的神经网络激活函数比如逻辑函数,双曲函数以及sigmoid函数等,relu函数,可以使络可以自行引⼊稀疏性,同时⼤⼤地提⾼了训练速度。最后的输出层的输出大小设为10,并激活了softmax函数,即归一化指数函数。

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28, 1)), 
    tf.keras.layers.Dense(units =100, activation='relu'),
    tf.keras.layers.Dense(units =100, activation='relu'),
    tf.keras.layers.Dense(units =10,activation='softmax')])

5.定义优化器和损失函数

        人工神经网络是由很多神经元组成的,每个神经元都有自己的权重w,表示在某项任务中,该神经元的重要程度。训练的过程,其实就是计算合适的w和b的过程。合适的w和b的要求就是预测值与真实值相差不大。即,真实值减去预测值,取绝对值后求和。训练的过程,可以粗略的理解成:调节 w 和 b, 使 loss 尽可能小。对w和b参数的调节,就是优化器(optimizer)需要做的,这就是优化器的作用。此处我们利用优化器中的Adam函数,这也是如今最常用的优化器之一。

        损失函数是将随机事件或其有关随机变量的取值映射为非负实数以表示该随机事件的“风险”或“损失”的函数。损失函数通常作为学习准则与优化问题相联系,即通过最小化损失函数求解和评估模型。这里我们使用交叉熵损失函数Sparse_Categorical_Cross_entropy。

optimizer = tf.keras.optimizers.Adam()
loss_func = tf.keras.losses.SparseCategoricalCrossentropy()

6.编译模型与训练

        首先输出优化器optimizer和损失函数loss_func,并利用精度评估函数metrics对relu函数得到的预测结果进行评估。

        之后利用fit函数返回一个History的对象,也就是多进行几次多层感知机的训练。用epochs定义训练的总轮数。在这里我们设置epochs为3。当epochs过小时,准确率会很低,而过大时,会浪费很多的时间,但是准确率的提高不会很明显。总和准确率和训练效率,我找到3这个数是非常适合本次训练的。代码如图。

model.compile(optimizer=optimizer,loss=loss_func,metrics=['accuracy'])   
history = model.fit(dataset,validation_data=test_dataset,epochs=3)

经过验证,如下图,三轮训练后准确率可以达到95%以上 ,说明该模型较为可靠,多层感知机的参数设置也较为合理。

7.模型预测

        首先输出需要测试的图像,如下:

通过多层感知机实现MNIST手写体识别_第1张图片

         然后输出预测结果:

         代码:

pre = model.predict(test_dataset)
plt.imshow(test_image[0])
plt.show()
print(pre)
print("预测结果:",np.argmax(pre[0]))

 8.完整代码

import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
(train_image, train_labels), (test_image, test_labels) = tf.keras.datasets.mnist.load_data()
train_image = tf.expand_dims(train_image, -1)
test_image = tf.expand_dims(test_image, -1)
train_image = tf.cast(train_image/255, tf.float32)
test_image = tf.cast(test_image/255, tf.float32)
train_labels = tf.cast(train_labels, tf.int64)
test_labels = tf.cast(test_labels, tf.int64)
dataset = tf.data.Dataset.from_tensor_slices((train_image, train_labels)).shuffle(60000).batch(256)
test_dataset = tf.data.Dataset.from_tensor_slices((test_image, test_labels)).batch(256)
model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28, 1)), 
    tf.keras.layers.Dense(units =100, activation='relu'),
    tf.keras.layers.Dense(units =100, activation='relu'),
    tf.keras.layers.Dense(units =10,activation='softmax')])
optimizer = tf.keras.optimizers.Adam()
loss_func = tf.keras.losses.SparseCategoricalCrossentropy()
model.compile(optimizer=optimizer,loss=loss_func,metrics=['accuracy'])   
history = model.fit(dataset,validation_data=test_dataset,epochs=3)
pre = model.predict(test_dataset)
plt.imshow(test_image[0])
plt.show()
print(pre)
print("预测结果:",np.argmax(pre[0]))

你可能感兴趣的:(深度学习,python,人工智能)