基于keras训练mnist数据集-全连接网络

本文详细介绍使用Keras库构建神经网络,实现MNIST手写数字分类任务的全过程,包括数据加载、预处理、模型搭建、训练及评估。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

—简述

这是一个简单的神经网络示例,使用python的Keras库来训练手写数字分类。对于初学者来说,可能无法立刻搞懂这个示例的全部内容。但是没关系,下面我将会详细说明示例中每个步骤。
MNIST问题也被看做是深度学习的“Hello world”,对于零基础想学习深度学习的初学者来说是一个不错的选择,之所以选择keras,是因为它具有以下重要特性:

  • 相同的代码可以在CPU或GPU上无缝切换运行
  • 具有用户友好的API,便于快速开发深度学习模型的原型。
  • 内置支持卷积网络(用于计算机视觉)、循环网络(用于序列处理)以及二者的任意组合。
  • 支持任意网络架构:多输入或多输出模型、层共享、模型共享等。这也就是说,Keras能够构建任意深度学习模型,无论是生成式对抗网络还是神经图灵机。

言归正传,下面给出具体实例过程:

1、加载MNIST数据集

MNIST数据集是由 60000 张训练图像和 10000 张测试图像组成,图像大小是 28 x 28 的灰度图像,已经预先加载在了Keras库中,其中包括4个Numpy数组。

# 加载Keras中的MNIST数据集
from keras.datasets import mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

其中 train_images 和 train_labels 组成训练集(training set),模型将从此数据集进行学习,test_images 和 test_labels 一起组成测试集,用于对模型进行测试。

也可以将上述数据集进行打印,查看具体内容,

>> train_image.shape
(6000, 28, 28)
>> train_labels
array([5, 0, 4, ..., 6, 8], dtype=uint8)

2、图像数据预处理

要对加载的数据进行预处理,以适应网络要求的形状,并将所有值缩放到[ 0, 1] 之间,由于我们训练的图像是 28 x 28 的灰度图,被保存在 uint8 类型的数组中,也就是值的范围在 [0, 255] 之间,形状为 (60000, 28, 28),所以最后要转换为一个 float32 数组, 其形状变为 (60000, 28 * 28),取值范围为 0~1。

# 准备图像数据
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255

test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255

# 准备标签,需要对标签进行分类编码转换成二进制格式
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)

# 为了验证训练的模型,此处从训练集中取出 1/3 的数据应于验证训练的模型
x_val = train_images[:20000]
partial_x_train = train_images[20000:]

y_val = train_labels[:20000]
partial_y_train = train_labels[20000:]

3、模型定义

下面是构建网络模型的过程,模块 layers 可以看作是构建网络层的工具,模块 models 可以看作是创建网络模型的一个容器,可以把创建的网络层加入到这个容器中。

# 导入数据处理模块,可以看作
from keras import models
from keras import layers

# 一个空的网络结构
model = models.Sequential()

# 添加两个全连接层
model.add(layers.Dense(512, activation='relu', input_shape=(28*28,)))
model.add(layers.Dense(10, activation='softmax'))

4、编译模型

代码很短只需一行,但需要设置三个参数,其中

  • loss: 所代表的是损失函数,使网络模型训练数据朝向正确的方向前进。
  • optimizer: 基于训练数据和损失函数来更新网络的机制。
  • metric: 在训练和测试过程中需要监控的指标,本例只关心精度,即正确分类的图像所占的比例。
# 设置训练网络的必要参数,如果要用到其他优化器还需要导入模块 optimizers
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])

5、训练模型

也就是在训练数据上拟合模型,其中前两个参数为训练数据,即,包含图像和标签的数据。

  • epochs 为迭代次数,即训练整个数据集要迭代的次数,可根据机器性能设置参数,详细调参后续文章会叙述。
  • batch_size 表示每次训练数据按此批量大小进行训练,也可以是其它参数,但是最好取 2 的整数倍。
  • validation_data 为验证模型的数据集,即验证集。
history = model.fit(partial_x_train, 
					partial_y_train, 
					epochs=20,  
					batch_size=128,
					validation_data=(x_val, y_val))
					
# 评估模型,即在测试集上的性能
test_loss, test_acc = model.evaluate(test_images, test_labels)

可以对上述数据进行打印,如

>>print('test_acc:', test_acc)
test_acc: 0.9809
>>history_dict = history.history
>>history_dict.keys()
dict_keys(['val_loss', 'val_acc', 'loss', 'acc'])

部分训练过程如下:
AIL

6、绘制训练结果

  • 绘制训练损失与验证损失的训练结果
import matplotlib.pyplot as plt

# 纵坐标,所需绘制的数据
history_dict = history.history
loss_values = history_dict['loss']
val_loss_values = history_dict['val_loss']

# 横坐标,步长
epochs = range(1, len(loss_values) + 1)

# 绘制图像
plt.plot(epochs, loss_values, 'bo', label='Training loss')
plt.plot(epochs, val_loss_values, 'b', label='Validation loss')

# 标题
plt.title('Training and validation loss')

# 横、纵坐标标签
plt.xlabel('Epochs')
plt.ylabel('Loss')

# 自适应标签的位置
plt.legend()

# 显示图像
plt.show()

结果如下:
AIL

  • 绘制训练精度与验证精度的训练结果
# 清除图像
plt.clf()

acc = history_dict['acc']
val_acc = history_dict['val_acc']

plt.plot(epochs, val_acc, 'bo', label='Training acc')
plt.plot(epochs, acc, 'b', label='Validation acc')

plt.title('Training and validation acc')

plt.xlabel('Epochs')
plt.ylabel('Acc')

plt.legend()

plt.show()

结果如下:
在这里插入图片描述

7、预测图像

现在我们来预测未训练的图像(测试集)并显示出来,首先重新加载 MNIST 数据集,因为前面过程预处理使得图像数据格式变化。

(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
predictions = model.predict(test_images)

可以将数据打印出来,得到是一个张量的形式,每个向量中包含有 10 数据,代表是 0~9 某个数字的概率。结果如下

>>print(predictions)
[[8.0789969e-15 3.0667143e-20 4.9133229e-13 ... 1.0000000e+00
  7.1623703e-16 6.8349046e-12]
 [6.9563542e-22 5.9805968e-16 1.0000000e+00 ... 0.0000000e+00
  2.3937719e-17 2.0886891e-33]
 [1.8092266e-13 9.9999917e-01 2.1047970e-09 ... 1.1447231e-07
  7.2424598e-07 5.0652759e-12]
 ...
 [1.4542224e-27 4.8825887e-20 6.9998436e-24 ... 4.1665107e-14
  2.3709947e-12 7.7242823e-11]
 [3.8461803e-22 6.4347756e-23 1.8406260e-26 ... 6.4342509e-26
  4.2752926e-11 2.6701102e-24]
 [1.3350630e-23 2.6857994e-33 6.6915423e-23 ... 9.5699816e-33
  9.6743583e-28 1.2382327e-28]]
>> import numpy as np
>> np.argmax(predictions[10]) 
0

上述测试了测试集 test_images 中第10个图像的数字是0,为了验证是不是准确的我们将 test_images 中
第10个图像打印出来,结果如下

>> tes = test_images[10]
>> plt.imshow(tes, cmap=plt.cm.binary)
>> plt.show()

ail
结果显示我们预测的结果是准确的。
完整代码如下:

from keras.datasets import mnist
from keras import models
from keras import layers
from keras.utils import to_categorical
import matplotlib.pyplot as plt

(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255

test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255

train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)

x_val = train_images[:20000]
partial_x_train = train_images[20000:]

y_val = train_labels[:20000]
partial_y_train = train_labels[20000:]


network = models.Sequential()
network.add(layers.Dense(512, activation='relu', input_shape=(28*28,)))
network.add(layers.Dense(10, activation='softmax'))

network.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])

history = network.fit(partial_x_train, partial_y_train, epochs=20, batch_size=128, validation_data=(x_val, y_val))
test_loss, test_acc = network.evaluate(test_images, test_labels)

# 纵坐标,所需绘制的数据
history_dict = history.history
loss_values = history_dict['loss']
val_loss_values = history_dict['val_loss']

# 横坐标,步长
epochs = range(1, len(loss_values) + 1)

# 绘制图像
plt.plot(epochs, loss_values, 'bo', label='Training loss')
plt.plot(epochs, val_loss_values, 'b', label='Validation loss')

# 标题
plt.title('Training and validation loss')

# 横、纵坐标标签
plt.xlabel('Epochs')
plt.ylabel('Loss')

# 自适应标签的位置
plt.legend()

# 显示图像
plt.show()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值