机器学习第一周:用卷积神经网络实现Mnist手写数字识别(付基础知识解释)

MNIST 数据集是一个手写数字识别数据集,包含了 60000 张训练图像和 10000 张测试图像,每张图像都是 28x28 像素的灰度图像。在这个代码中,我们使用了 Keras 中的 Sequential 类来定义模型,并通过 model.add() 方法向其中添加各种层。Sequential 类是 Keras 中的一种模型类型,可以用来构建序列模型。序列模型是一个线性的层次结构,可以通过将神经网络层按顺序堆叠来构建。在这个代码中,我们首先添加了一个卷积层,然后是一个最大池化层,
摘要由CSDN通过智能技术生成

Mnist手写数字数据集介绍

MNIST 数据集是一个手写数字识别数据集,包含了 60000 张训练图像和 10000 张测试图像,每张图像都是 28x28 像素的灰度图像。

代码整体结构

  1. 在这个代码中,我们首先使用了 numpy 库中的 np.random.seed() 方法来设置随机种子,以确保结果可重复。

  1. 然后,我们使用了 Keras 中的 mnist.load_data() 方法来加载 MNIST 数据集。

  1. 接着,我们将数据转换为 float 类型并归一化,将标签转换为 one-hot 编码。

  1. 最后,我们定义了一个卷积神经网络模型,并使用 model.compile() 方法来编译模型,使用 model.fit() 方法来训练模型,使用 model.evaluate() 方法来评估模型。

其中,模型的损失函数为 categorical_crossentropy,优化器为 adam,评估指标为 accuracy。

构建网络的思路

这个例子中,我们使用了 Keras 框架来构建模型,使用了 Sequential 类来定义模型,并通过 model.add() 方法向其中添加各种层。

Sequential 类是 Keras 中的一种模型类型,可以用来构建序列模型。

序列模型是一个线性的层次结构,可以通过将神经网络层按顺序堆叠来构建。

在这个代码中,我们

  1. 首先添加了一个卷积层,

  1. 然后是一个最大池化层,

  1. 接着是一个 Dropout 层,

  1. 然后是一个 Flatten 层,

  1. 最后是两个全连接层。

其中,卷积层和最大池化层用于提取图像特征,

Dropout 层用于防止过拟合,

Flatten 层用于将多维输入展平为一维,

全连接层用于分类。

代码解析

#  -*- coding: utf-8 -*-

# 导入所需的库
import numpy as np
from keras.datasets import mnist 
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.utils import np_utils

导入所需模块

from keras.models import Sequential

keras.models 这个模块中包含了 Sequential 这个类,它是 Keras 中的一种模型类型,可以用来构建序列模型。序列模型是一个线性的层次结构,可以通过将神经网络层按顺序堆叠来构建。在这个代码中,我们使用 Sequential 类来定义模型,并通过 model.add() 方法向其中添加各种层。

from keras.layers import Dense, Dropout, Flatten

这句代码是导入了 Keras 中的 Dense、Dropout 和 Flatten 三个类。

其中,

  • Dense 类是 Keras 中的一种全连接层,

  • Dropout 类是 Keras 中的一种正则化层,

  • Flatten 类是 Keras 中的一种展平层。

在这个代码中,我们将这三个类导入到了当前的命名空间中,以便在后续的代码中使用。

具体来说,

Dense 类用于定义全连接层,它的作用是将输入和权重矩阵相乘,并加上偏置向量,然后将结果传递给激活函数。

Dropout 类用于定义正则化层,它的作用是在训练过程中随机地将一些神经元的输出设置为0,以防止过拟合。

Flatten 类用于定义展平层,它的作用是将多维输入展平为一维,以便于后续的全连接层进行处理。

因此,这三个类在卷积神经网络中都扮演着非常重要的角色。

from keras.layers.convolutional import Conv2D, MaxPooling2D

其中,

  • Conv2D 类是 Keras 中的一种卷积层,

  • MaxPooling2D 类是 Keras 中的一种最大池化层。

在这个代码中,我们将这两个类导入到了当前的命名空间中,以便在后续的代码中使用。

卷积层和最大池化层是卷积神经网络中最为基础的两种层,它们可以用于提取图像特征。

  • 卷积层通过对输入图像进行卷积操作,提取出其中的特征,

  • 而最大池化层则通过对输入图像进行最大池化操作,进一步提取出其中的主要特征。

这两种层的结合可以有效地提高卷积神经网络的性能。

keras.layers模块中还有一个Convolutional层,它是Conv2D的别名,用于处理图像数据的二维卷积层。

from keras.utils import np_utils

这句代码是导入了 Keras 中的 np_utils 模块,它包含了 to_categorical() 方法,可以将标签转换为 one-hot 编码。

在这个代码中,我们使用了 to_categorical() 方法将训练集和测试集的标签都转换为了 one-hot 编码,以便于后续的模型训练和评估。

在机器学习中,我们通常需要将分类变量转换为数值变量,以便于计算机进行处理。

而 one-hot 编码就是一种常用的分类变量转换方式。它将每个分类变量转换为一个二进制向量,向量的长度等于分类变量的取值个数,向量中只有一个元素为 1,其余元素都为 0。

例如,

对于一个有三个分类变量的数据集,

其中

  • 分类变量 A 有两个取值,

  • 分类变量 B 有三个取值,

  • 分类变量 C 有四个取值,

那么对于每个样本,我们可以

  • 将分类变量 A 转换为一个长度为 2 的二进制向量,

  • 分类变量 B 转换为一个长度为 3 的二进制向量,

  • 分类变量 C 转换为一个长度为 4 的二进制向量,

然后将这三个向量拼接起来,得到一个长度为 9 的向量,

这个向量就是该样本的 one-hot 编码。

这种编码方式可以保留分类变量之间的关系,同时也便于计算机进行处理。

设置随机种子,确保结果可重复

# 设置随机种子,确保结果可重复
seed = 7
np.random.seed(seed)

在机器学习中,我们通常需要使用随机数来初始化模型参数、划分数据集、打乱数据集等。

然而,由于计算机生成的随机数是伪随机数,其生成过程是基于一个初始种子的,因此如果我们不设置随机种子,那么每次运行程序时生成的随机数序列都是不同的,这会导致模型的训练结果不可重复。

为了确保结果的可重复性,我们可以在程序中设置随机种子,这样每次运行程序时生成的随机数序列都是相同的,从而保证了模型的训练结果是可重复的。

在这个代码中,我们使用了 numpy 库中的 np.random.seed() 方法来设置随机种子,以确保结果可重复。

在机器学习中,我们通常需要对模型进行调参、比较不同算法的性能等。

如果每次运行程序时得到的结果都是不同的,那么我们就无法进行有意义的比较和分析。

因此,为了确保实验结果的可重复性,我们需要保证每次运行程序时得到的结果都是相同的。

这就是为什么要保证结果的可重复性的原因。

加载数据

(X_train, y_train), (X_test, y_test) = mnist.load_data()

这句代码的作用是使用 Keras 中的 mnist.load_data() 方法来加载 MNIST 数据集,并将训练集和测试集分别赋值给 X_train、y_train 和 X_test、y_test 四个变量。

其中,X_train 和 X_test 分别是训练集和测试集的图像数据,y_train 和 y_test 分别是训练集和测试集的标签数据。

这个方法会返回两个元组,第一个元组包含了训练集的图像数据和标签数据,第二个元组包含了测试集的图像数据和标签数据。

因此,这句代码的作用就是将 MNIST 数据集加载到内存中,以便后续的模型训练和评估。

这种赋值方法叫做元组解包(Tuple Unpacking),可以将一个元组中的多个元素分别赋值给多个变量。

在这个例子中,mnist.load_data() 方法返回了两个元组,第一个元组包含了训练集的图像数据和标签数据,第二个元组包含了测试集的图像数据和标签数据。

通过元组解包的方式,我们可以将这两个元组中的四个数组分别赋值给 X_train、y_train、X_test 和 y_test 四个变量。

这样做的好处是可以简化代码,使代码更加清晰易懂。

使用元组解包的方式需要提前知道数据集的结构,即数据集返回的是一个包含多个元素的元组,每个元素分别代表了数据集中的一个部分。

在这个例子中,mnist.load_data() 方法返回的是一个包含两个元素的元组,第一个元素是一个包含了训练集图像数据和标签数据的元组,第二个元素是一个包含了测试集图像数据和标签数据的元组。

因此,我们可以使用元组解包的方式将这两个元组中的四个数组分别赋值给 X_train、y_train、X_test 和 y_test 四个变量。

如果不知道数据集的结构,就无法使用元组解包的方式来赋值。

MNIST 数据集的结构可以通过查看 Keras 或 TensorFlow 的文档来了解。

以 Keras 为例,可以在 Keras 的官方文档中找到 MNIST 数据集的说明,其中包括了数据集的结构、数据集的下载和解压缩方法、数据集的格式等信息。

具体来说,可以在 Keras 的文档中找到以下内容:

  • keras.datasets.mnist.load_data() 方法的说明,包括了方法的参数、返回值、使用方法等信息。

  • MNIST 数据集的说明,包括了数据集的下载和解压缩方法、数据集的格式、数据集的大小等信息。

  • MNIST 数据集的示例代码,包括了如何使用 MNIST 数据集来训练和评估模型的示例代码。

通过查看文档,可以了解到 MNIST 数据集的结构是一个包含两个元素的元组,第一个元素是一个包含了训练集图像数据和标签数据的元组,第二个元素是一个包含了测试集图像数据和标签数据的元组。

因此,我们可以使用元组解包的方式将这两个元组中的四个数组分别赋值给 X_train、y_train、X_test 和 y_test 四个变量。

将数据转换为float类型并归一化

X_train = X_train.astype('float32') / 255
X_test = X_test.astype('float32') / 255

这句代码的作用是将训练集的图像数据 X_train 转换为 float32 类型,并将其归一化。

具体来说,

它将 X_train 中的每个像素值除以 255,得到的结果就是一个 0 到 1 之间的浮点数,表示该像素点的亮度值。

这个操作可以将像素值的范围从 0 到 255 缩放到 0 到 1 之间,

使得模型更容易学习到图像中的特征。

在深度学习中,数据的归一化是一种常用的数据预处理方式,它可以使得模型更加稳定、收敛更快、泛化能力更强。

具体来说,归一化可以带来以下几个好处:

提高模型的稳定性:

在深度学习中,模型的训练过程往往是通过梯度下降算法来实现的。如果数据的范围过大,那么在计算梯度时就会出现梯度爆炸的问题,导致模型的训练不稳定。通过归一化可以将数据的范围缩放到一个合适的范围内,避免了梯度爆炸的问题,提高了模型的稳定性。

提高模型的收敛速度:

在深度学习中,模型的训练过程往往需要迭代很多次才能收敛。如果数据的范围过大,那么每次迭代的步长就会很大,导致模型的收敛速度很慢。通过归一化可以将数据的范围缩放到一个合适的范围内,使得每次迭代的步长更加合适,从而提高了模型的收敛速度。

提高模型的泛化能力:

在深度学习中,模型的泛化能力是指模型对未见过的数据的适应能力。如果数据的范围过大,那么模型就会过度拟合训练数据,导致泛化能力不足。通过归一化可以将数据的范围缩放到一个合适的范围内,

在深度学习中,模型的训练过程往往是通过梯度下降算法来实现的。在梯度下降算法中,每次迭代的更新量是由梯度和学习率共同决定的。

如果数据的范围过大,那么在计算梯度时就会出现梯度爆炸的问题,导致模型的训练不稳定。

具体来说,如果数据的范围过大,那么在计算梯度时,梯度的值也会变得很大,从而导致模型的参数更新量也变得很大。

如果更新量过大,就会导致模型的训练不稳定,甚至无法收敛。

因此,为了避免梯度爆炸的问题,需要对数据进行归一化处理,将数据的范围缩放到一个合适的范围内。

<

  • 8
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值