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

Mnist手写数字数据集介绍

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

代码整体结构

  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 之间,

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

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

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

提高模型的稳定性:

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

提高模型的收敛速度:

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

提高模型的泛化能力:

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

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

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

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

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

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

将标签转换为one-hot编码

y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)

定义模型

model = Sequential()

model.add(Conv2D(32, (5, 5), input_shape=(28, 28, 1), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.1))
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dense(10, activation='softmax'))

在这个代码中,我们使用了 Keras 中的 Sequential 类来定义模型,并通过 model.add() 方法向其中添加各种层。

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

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

在这个代码中,我们

  • 首先添加了一个卷积层,

  • 然后是一个最大池化层,

  • 接着是一个 Dropout 层,

  • 然后是一个 Flatten 层,

  • 最后是两个全连接层。

其中,

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

Dropout 层用于防止过拟合,

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

全连接层用于分类。

model.add(Conv2D(32, (5, 5), input_shape=(28, 28, 1), activation=’relu’))

这句代码的作用是向模型中添加一个卷积层。

具体来说,

它使用了 Keras 中的 Conv2D 类来定义一个卷积层,

并通过 model.add() 方法将其添加到模型中。

Conv2D 类是 Keras 中的一种神经网络层类型,可以用来构建卷积神经网络。

卷积神经网络是一种常用的深度学习模型,可以用于图像分类、目标检测、图像分割等任务。

这个卷积层的参数如下:

filters:

卷积核的数量,即输出的通道数。这个参数可以理解为卷积层中卷积核的个数,每个卷积核可以提取一种特征。在这个代码中,我们设置了 32 个卷积核,即输出的通道数为 32。

kernel_size:

卷积核的大小,即卷积窗口的大小。这个参数可以理解为卷积核的宽度和高度。在这个代码中,我们设置了卷积核的大小为 (5, 5),即卷积窗口的宽度和高度都为 5。

input_shape:

输入数据的形状,即输入数据的通道数、宽度和高度。在这个代码中,我们设置了输入数据的形状为 (28, 28, 1),即输入数据的通道数为 1,宽度和高度都为 28。这个参数只需要在第一层卷积层中设置,后面的卷积层会自动推断输入数据的形状。

activation:

激活函数的类型。在这个代码中,我们使用了 ReLU 激活函数,即 activation=’relu’。

因此,这句代码的作用就是向模型中添加一个卷积层,用于提取图像中的特征。这个卷积层有 32 个卷积核,每个卷积核的大小为 (5, 5),输入数据的形状为 (28, 28, 1),激活函数的类型为 ReLU。

超参数

超参数是指在模型训练之前需要手动设置的参数,这些参数不能通过训练得到,需要人工指定。

超参数包括学习率、正则化系数、批大小、卷积核个数等。

超参数的选择对模型的性能有很大的影响,不同的超参数组合会导致不同的模型性能。

因此,超参数的选择是深度学习模型调参中非常重要的一步。

常用的超参数选择方法包括网格搜索、随机搜索、贝叶斯优化等。

卷积核个数

卷积核的个数是一个超参数,需要根据具体的任务和数据集来确定。

一般来说,卷积核的个数越多,模型的表达能力就越强,但同时也会增加模型的复杂度和计算量。

因此,在实际应用中,我们需要根据具体情况来确定卷积核的个数。

一种常用的方法是通过交叉验证来选择最优的超参数。

另外,一些经验性的规则也可以作为卷积核个数的参考,

比如在 LeNet 中,第一层卷积层的卷积核个数为 6,第二层卷积层的卷积核个数为 16。

卷积核大小

卷积核的大小是一个超参数,需要根据具体的任务和数据集来确定。

一般来说,

卷积核的大小越小,模型的感受野就越小,可以提取更细节的特征;

卷积核的大小越大,模型的感受野就越大,可以提取更全局的特征。

因此,在实际应用中,我们需要根据具体情况来确定卷积核的大小。

一种常用的方法是通过交叉验证来选择最优的超参数。

另外,一些经验性的规则也可以作为卷积核大小的参考,

比如在 LeNet 中,第一层卷积层的卷积核大小为 5×5,第二层卷积层的卷积核大小为 5×5。

ReLU激活函数

ReLU(Rectified Linear Unit)激活函数是一种常用的非线性激活函数,它的表达式为 f(x) = max(0, x)。ReLU 激活函数的优点是计算简单、收敛速度快、不会出现梯度消失等问题。

在深度学习中,ReLU 激活函数被广泛应用于卷积神经网络和全连接神经网络中。

激活函数

激活函数是神经网络中的一种非线性函数,它的作用是引入非线性因素,增强模型的表达能力。

在深度学习中,激活函数被广泛应用于卷积神经网络和全连接神经网络中。

常用的激活函数包括 Sigmoid、Tanh、ReLU 等。

其中,ReLU 是一种常用的非线性激活函数,它的表达式为 f(x) = max(0, x)。

ReLU 激活函数的优点是计算简单、收敛速度快、不会出现梯度消失等问题。

在实际应用中,我们需要根据具体情况来选择合适的激活函数。

model.add(MaxPooling2D(pool_size=(2, 2)))

这句代码的作用是向模型中添加一个最大池化层。

在深度学习中,最大池化层是一种常用的特征提取方式,它可以将输入的特征图进行下采样,从而减少特征图的大小和参数数量,提高模型的计算效率和泛化能力。

具体来说,

最大池化层会将输入的特征图分成若干个不重叠的区域,然后在每个区域中选择最大的特征值作为输出。

这个过程可以看作是对输入特征图进行下采样,从而减少特征图的大小和参数数量。

在这个代码中,我们使用了 Keras 中的 MaxPooling2D 类来定义最大池化层,并通过 model.add() 方法将其添加到模型中。

其中,pool_size 参数指定了池化窗口的大小,即每个区域的大小。

在这个代码中,我们将池化窗口的大小设置为 (2, 2),即每个区域的大小为 2×2。

这个值可以根据实际情况进行调整,一般来说,池化窗口的大小越大,下采样的程度就越大,特征图的大小就越小。

在深度学习中,池化窗口的大小是一个非常重要的超参数,它会直接影响模型的性能和泛化能力。一般来说,池化窗口的大小越大,下采样的程度就越大,特征图的大小就越小。

但是,如果池化窗口的大小过大,就会导致信息的丢失,从而影响模型的性能和泛化能力。

因此,我们需要根据实际情况来确定池化窗口的大小。

一般来说,我们可以通过交叉验证等方法来确定最优的池化窗口大小。

另外,池化窗口的大小也可以根据输入特征图的大小来确定。

如果输入特征图的大小比较小,那么池化窗口的大小也可以相应地调整为较小的值,以避免信息的丢失。反之,如果输入特征图的大小比较大,那么池化窗口的大小也可以相应地调整为较大的值,以减少特征图的大小和参数数量。

总之,池化窗口的大小需要根据实际情况进行调整,以达到最优的性能和泛化能力。

model.add(Dropout(0.2))

这句代码的作用是向模型中添加一个 Dropout 层,用于防止过拟合。

在深度学习中,过拟合是指模型在训练集上表现很好,但在测试集上表现很差的现象。

过拟合的原因是模型过于复杂,导致在训练集上出现了过多的细节和噪声,从而使得模型无法泛化到测试集上。

为了避免过拟合,我们可以使用一些正则化方法,如 Dropout、L1 正则化、L2 正则化等。

其中,Dropout 是一种常用的正则化方法,它可以在训练过程中随机地将一些神经元的输出置为 0,从而使得模型更加鲁棒,防止过拟合。

具体来说,

这句代码中的 Dropout(0.2) 表示在训练过程中随机地将 20% 的神经元的输出置为 0。

这个参数可以根据具体的情况进行调整,一般来说,当模型比较复杂时,需要使用较大的 Dropout 比例,以防止过拟合。

在这个代码中,我们将 Dropout 层添加到了卷积层和最大池化层之间,这是因为卷积层和最大池化层用于提取图像特征,而 Dropout 层可以防止过拟合,从而使得模型更加鲁棒。

以上这句有疑问,没有在中间吧?

在深度学习模型中,Dropout 层是一种常用的正则化技术,用于防止过拟合。Dropout 层的作用是在训练过程中随机丢弃一部分神经元,从而减少神经元之间的依赖关系,增强模型的泛化能力。

具体来说,Dropout 层会在每次训练迭代中随机选择一些神经元,并将它们的输出值设置为 0。这样一来,模型就不会过度依赖某些神经元,从而减少了过拟合的风险。

在深度学习模型中,Dropout 层通常被添加到全连接层之后,用于减少全连接层中神经元之间的依赖关系。

此外,Dropout 层还可以被添加到卷积层和池化层之后,用于减少卷积层和池化层中神经元之间的依赖关系。

在这个代码中,我们将 Dropout 层添加到了卷积层和最大池化层之后,用于减少这些层中神经元之间的依赖关系,增强模型的泛化能力。

同时,我们还将 Flatten 层添加到了 Dropout 层之后,用于将 Dropout 层的输出展平为一维,以便后续的全连接层进行分类。

在这个代码中,没有全连接层。这个代码中的模型是一个卷积神经网络,包含了卷积层、最大池化层、Dropout 层和 Flatten 层。

卷积层和最大池化层用于提取输入数据中的特征,Dropout 层用于减少神经元之间的依赖关系,Flatten 层用于将多维输入展平为一维。

在这个代码中,我们将 Flatten 层添加到了 Dropout 层之后,用于将 Dropout 层的输出展平为一维,以便后续的全连接层进行分类。

以上这段有点逻辑不清,待整理

model.add(Flatten())

这句代码的作用是向模型中添加一个 Flatten 层。

Flatten 层是 Keras 中的一种层类型,用于将多维输入展平为一维。

在这个代码中,我们将 Flatten 层添加到了卷积层、最大池化层和 Dropout 层之后,用于将这些层的输出展平为一维,以便后续的全连接层进行分类。

具体来说,

如果输入的数据是一个形状为 (batch_size, height, width, channels) 的张量,那么 Flatten 层的作用就是将其展平为一个形状为 (batch_size, height * width * channels) 的张量。

这个操作可以将多维输入转换为一维输入,使得模型更容易学习到输入数据中的特征。

model.add(Dense(128, activation=’relu’))

这句代码的作用是向模型中添加一个全连接层,该层的神经元个数为 128,激活函数为 relu。

全连接层是神经网络中最常用的一种层,它的每个神经元都与上一层的所有神经元相连。

在这个代码中,我们使用了 Dense 类来定义全连接层,并通过 model.add() 方法将其添加到模型中。Dense 类是 Keras 中的一种层类型,可以用来定义全连接层。

在这个代码中,我们将 Dense 类的第一个参数设置为 128,表示该层的神经元个数为 128。

激活函数是 relu,它是一种常用的非线性激活函数,可以将负数的输出值设为 0,从而实现非线性变换。通过添加这个全连接层,我们可以将模型的输出从卷积层和池化层的多维张量转换为一维向量,然后再通过全连接层进行分类。

神经元个数

在神经网络中,神经元个数是一个非常重要的超参数,它的大小会直接影响模型的性能。

通常情况下,神经元个数越多,模型的拟合能力就越强,但也会导致过拟合的问题。

因此,我们需要根据具体的问题来确定神经元个数。

一般来说,我们可以通过交叉验证等方法来确定神经元个数。

具体来说,我们可以先将数据集分成训练集和验证集,然后在训练集上训练模型,并在验证集上评估模型的性能。

我们可以尝试不同的神经元个数,然后选择在验证集上性能最好的模型。

另外,一些经验法则也可以用来确定神经元个数。

例如,对于一个输入特征维度为 n 的问题,我们可以将神经元个数设置为 n 的两倍。

这个经验法则并不是绝对的,但可以作为一个起点来进行调参。

model.add(Dense(10, activation=’softmax’))

这句代码的作用是向模型中添加一个全连接层,该层的输出维度为 10,激活函数为 softmax。

在深度学习中,softmax 函数常用于多分类问题中,它可以将一个 K 维的向量归一化为一个概率分布,其中 K 表示类别的数量。

具体来说,softmax 函数的输入是一个 K 维的向量 z,输出是一个 K 维的向量 y,其中 y[i] 表示输入属于第 i 个类别的概率。

softmax 函数的公式如下所示:

$$y_i = \frac{e^{z_i}}{\sum_{j=1}^K e^{z_j}}$$

          

其中,

$z_i$ 表示输入属于第 i 个类别的得分,

$e^{z_i}$ 表示将得分转换为概率的操作,

$\sum_{j=1}^K e^{z_j}$ 表示对所有类别的得分进行求和,以保证输出是一个概率分布。

softmax 函数的输出可以看作是对输入的一种归一化,它可以将输入的得分转换为概率,从而方便进行分类。

在这个代码中,我们向模型中添加了一个全连接层,该层的输出维度为 10,激活函数为 softmax。这个全连接层的作用是将前面的层的输出转换为一个概率分布,从而方便进行分类。

具体来说,该层的输入是一个 128 维的向量,输出是一个 10 维的向量,其中每个元素表示输入属于对应类别的概率。

因此,该层的输出可以看作是对输入的一种归一化,它可以将输入的得分转换为概率,从而方便进行分类。

至于为什么 Dense 层的输出维度是 128,这是由模型的设计决定的。

在这个代码中,我们可以看到模型的第一层是一个 Flatten 层,它的作用是将输入的图像数据展平成一个一维向量。

展平后的向量的维度是 28*28=784,因此我们可以将其作为全连接层的输入,从而得到一个 128 维的向量。

这个 128 维的向量可以看作是对输入的一种抽象,它包含了输入的一些重要特征,可以用于后续的分类任务。

因此,我们选择了 128 作为全连接层的输出维度。

当然,这个值也可以根据具体的任务进行调整,比如可以尝试使用更大或更小的值来得到更好的性能。

编译模型

model.compile(
    loss='categorical_crossentropy', 
    optimizer='adam',
    metrics=['accuracy']
)

这句代码的作用是编译模型。

在深度学习中,编译模型是一个必要的步骤,它会将模型的结构和训练方式组合在一起,并生成一个可执行的计算图。

具体来说,编译模型需要指定三个参数:

  • 损失函数、

  • 优化器和

  • 评估指标。

损失函数用于衡量模型在训练过程中的误差,它是模型优化的目标。

在这个代码中,我们使用了 categorical_crossentropy 作为损失函数。

categorical_crossentropy 是一个常用的多分类损失函数,它可以用于将模型的输出与真实标签进行比较,并计算出模型的误差。

具体来说,categorical_crossentropy 的计算公式如下所示:

$$L(y, \hat{y}) = -\sum_{i=1}^n y_i \log \hat{y}_i$$

其中,

$y$ 表示真实标签,

$\hat{y}$ 表示模型的输出,

$n$ 表示类别的数量。

该公式的含义是:

对于每个样本,计算其真实标签和模型输出之间的交叉熵,然后将所有样本的交叉熵求和,得到模型的总误差。

优化器用于更新模型的参数,它是模型训练的核心。

在这个代码中,我们使用了 adam 作为优化器。

adam 是一种常用的自适应学习率优化器,它可以根据梯度的大小自动调整学习率,从而加速模型的收敛。

具体来说,adam 的更新公式如下所示:

$$\theta_{t+1} = \theta_t - \frac{\alpha}{\sqrt{\hat{v}_t} + \epsilon} \hat{m}_t$$

其中,

$\theta_t$ 表示模型参数的当前值,

$\alpha$ 表示学习率,

$\hat{m}_t$ 表示梯度的一阶矩估计,

$\hat{v}_t$ 表示梯度的二阶矩估计,

$\epsilon$ 是一个很小的数,用于防止除以零。

adam 的更新公式结合了动量法和自适应学习率的思想,可以在不同的数据集和模型上取得很好的效果。

评估指标用于衡量模型的性能,它可以帮助我们了解模型在测试集上的表现。

在这个代码中,我们使用了 accuracy 作为评估指标。

accuracy 是一个常用的分类指标,它可以用于计算模型在测试集上的准确率。

具体来说,accuracy 的计算公式如下所示:

$$accuracy = \frac{\sum_{i=1}^n \mathbb{I}(y_i = \hat{y}_i)}{n}$$
#可能有误

其中,

$y$ 表示真实标签,

$\hat{y}$ 表示模型的输出,

$n$ 表示样本的数量,

$\mathbb{I}$ 表示指示函数。

该公式的含义是:对于每个样本,如果其真实标签和模型输出相同,则计数器加一,最后将计数器的值除以样本数量,得到模型的准确率。

在这个代码中,我们使用了 Keras 框架来构建模型。Keras 是一个高级深度学习框架,它可以帮助我们快速构建和训练深度学习模型。

在 Keras 中,编译模型的方法是 compile,

它接受三个参数:loss、optimizer 和 metrics。

其中,loss 和 optimizer 的含义和上面介绍的一样,metrics 用于指定评估指标,可以是一个或多个。

在 Keras 中,常用的评估指标包括 accuracy、precision、recall、f1-score 等。

训练模型

model.fit(
    X_train.reshape(-1, 28, 28, 1), 
    y_train, 
    validation_data=(
        X_test.reshape(-1, 28, 28, 1), 
        y_test
    ), 
    epochs=10, 
    batch_size=200
)

这句代码的作用是训练模型。

在深度学习中,训练模型是一个非常重要的步骤,它可以使模型逐渐学习到数据的特征,并不断优化模型的参数,从而提高模型的性能。

具体来说,训练模型需要指定训练数据、验证数据、迭代次数和批次大小等参数。

这个代码中,我们使用了 fit 方法来训练模型。fit 方法接受五个参数:

  • 训练数据、

  • 训练标签、

  • 验证数据、

  • 验证标签和

  • 迭代次数。

其中,训练数据和训练标签用于训练模型,验证数据和验证标签用于评估模型的性能,迭代次数表示训练模型的轮数。

在每一轮训练中,模型会根据训练数据和标签计算出梯度,并使用优化器来更新模型的参数。

在训练过程中,我们可以观察模型在训练集和验证集上的表现,以便及时调整模型的超参数和结构。

在这个代码中,我们使用了 reshape 方法来将输入数据的形状从 (n, 784) 转换为 (n, 28, 28, 1),其中 n 表示样本数量。

这是因为我们的模型接受的输入形状是 (28, 28, 1),即一张灰度图像。

因此,我们需要将输入数据的形状转换为这个形状,才能将其输入到模型中进行训练。

在 reshape 方法中,如果某一维的值为 -1,那么 reshape 方法会根据数组的大小自动计算这一维的值,以保证数组的元素个数不变。

在这个例子中,由于我们不知道样本数量 n 的具体值,因此将其设为 -1,让 reshape 方法自动计算。

至于为什么要先将输入数据展平为一维,再恢复为二维的形状,这是因为在神经网络中,全连接层(Dense)的输入是一个一维向量,因此需要将输入数据展平为一维向量。

而卷积层(Conv2D)的输入是一个三维张量,因此需要将输入数据恢复为三维张量的形状。

??是的,全连接层通常在卷积层的后面。在卷积神经网络中,卷积层和池化层通常用于提取图像的局部特征,而全连接层则用于将这些局部特征组合起来,形成最终的分类结果。

具体来说,卷积层和池化层可以看作是对图像进行特征提取和降维的操作,它们可以提取出图像的局部特征,比如边缘、纹理等。而全连接层则可以将这些局部特征组合起来,形成最终的分类结果。

在卷积神经网络中,通常会先使用若干个卷积层和池化层对图像进行特征提取和降维,然后再使用若干个全连接层将这些局部特征组合起来,形成最终的分类结果。这样做的好处是可以减少全连接层的参数数量,从而降低模型的复杂度,提高模型的泛化能力。

另外,我们还指定了 batch_size 参数为 200。

batch_size 表示每次训练时使用的样本数量,它可以影响模型的训练速度和性能。

通常情况下,我们会将 batch_size 设置为 2 的幂次方,以便在 GPU 上进行高效的并行计算。

另外,我们还可以通过调整 batch_size 来控制模型的泛化能力和过拟合程度。

如果 batch_size 太小,模型可能会过度拟合训练数据,导致在验证集上的表现不佳;

如果 batch_size 太大,模型可能会失去一些泛化能力,导致在测试集上的表现不佳。

除了 batch_size,我们还可以通过调整其他超参数来优化模型的性能,例如学习率、优化器、损失函数、激活函数、正则化等。

在实际应用中,我们通常需要进行大量的实验和调参,才能找到最优的超参数组合。

评估模型

scores = model.evaluate(X_test.reshape(-1, 28, 28, 1), y_test, verbose=1)
print("Accuracy准确率: %.2f%%" % (scores[1] * 100)) 

这句代码的作用是评估模型在测试集上的性能,并输出模型的准确率。

在深度学习中,评估模型的性能是一个非常重要的步骤,它可以帮助我们了解模型在实际应用中的表现,并及时调整模型的超参数和结构。

具体来说,evaluate 方法可以用于评估模型在测试集上的性能。

evaluate 方法接受三个参数:

  • 测试数据、

  • 测试标签和

  • verbose。

其中,测试数据和测试标签用于评估模型的性能,verbose 表示是否输出详细信息。

如果 verbose=0,那么 evaluate 方法会在评估完成后返回一个包含两个值的列表,分别表示模型的总误差和准确率;

如果 verbose=1,那么 evaluate 方法会在评估过程中输出详细信息,例如每个批次的评估结果、进度条等。

在这个代码中,我们使用了 evaluate 方法来评估模型在测试集上的性能,并输出模型的准确率。

具体来说,我们将测试数据和测试标签作为 evaluate 方法的输入,然后将返回的结果保存在 scores 变量中。

最后,我们使用 print 函数输出模型的准确率,以百分比的形式显示。

#需要注意的是,模型的准确率并不是唯一的评估指标,我们还可以使用其他指标来评估模型的性能,例如精确率、召回率、F1 值等。

在实际应用中,我们需要根据具体的任务和数据集选择合适的评估指标,并综合考虑多个指标来评估模型的性能。

# python /Users/qianhe/cursor-tutor/Mnist.py

以上。

文末福利:Keras模块解析

keras包括以下模块:

  • keras.datasets: 包含了一些常用的数据集,如MNIST、CIFAR10等。

  • keras.models: 包含了一些常用的模型,如Sequential、Model等。

  • keras.layers: 包含了一些常用的层,如Dense、Conv2D、MaxPooling2D等。

  • keras.optimizers: 包含了一些常用的优化器,如SGD、Adam等。

  • keras.losses: 包含了一些常用的损失函数,如categorical_crossentropy、mse等。

  • keras.metrics: 包含了一些常用的评估指标,如accuracy、precision等。

  • keras.utils: 包含了一些常用的工具函数,如to_categorical等。

  • keras.callbacks: 包含了一些常用的回调函数,如EarlyStopping、ModelCheckpoint等。

  • keras.preprocessing: 包含了一些常用的数据预处理工具,如图像处理、序列处理等。

  • keras.applications: 包含了一些常用的预训练模型,如VGG16、ResNet50等。

  • keras.backend: 包含了一些常用的后端函数,如tf、th等。

keras.datasets: 包含了一些常用的数据集,如MNIST、CIFAR10等。

  • MNIST: 手写数字识别数据集

  • CIFAR10: 包含10个类别的彩色图像数据集

  • CIFAR100: 包含100个类别的彩色图像数据集

  • IMDB: 电影评论数据集,用于情感分析

  • Reuters: 新闻文本数据集,用于文本分类

  • Fashion-MNIST: 服装图像数据集,用于图像分类

  • Boston Housing: 波士顿房价数据集,用于回归分析

keras.models

  • Sequential: 顺序模型,用于按顺序堆叠各种神经网络层

  • Model: 泛型模型,用于构建任意的神经网络结构

  • load_model: 加载已经训练好的模型

  • save_model: 保存已经训练好的模型

  • clone_model: 克隆一个已经训练好的模型

  • model_from_json: 从JSON字符串中加载模型

  • model_from_yaml: 从YAML字符串中加载模型

keras.layers

  • Dense: 全连接层,每个神经元与上一层的所有神经元相连

  • Dropout: 随机失活层,用于防止过拟合

  • Flatten: 展平层,将多维输入展平为一维

  • Conv2D: 二维卷积层,用于处理图像数据

  • MaxPooling2D: 二维最大池化层,用于降低图像数据的空间维度

  • Activation: 激活函数层,用于引入非线性因素

  • Input: 输入层,用于指定输入数据的形状

  • Embedding: 嵌入层,用于将离散的输入数据映射到连续的向量空间

  • LSTM: 长短时记忆网络层,用于处理序列数据

  • GRU: 门控循环单元层,用于处理序列数据

  • BatchNormalization: 批量归一化层,用于加速训练过程

  • Concatenate: 拼接层,用于将多个输入数据拼接在一起

  • Add: 加法层,用于将多个输入数据相加

  • Multiply: 乘法层,用于将多个输入数据相乘

  • ZeroPadding2D: 二维零填充层,用于在图像边缘填充0

  • Cropping2D: 二维裁剪层,用于裁剪图像边缘

  • Lambda: 自定义层,用于定义任意的计算过程

keras.optimizers

  • SGD: 随机梯度下降优化器,用于优化线性模型和深度神经网络

  • RMSprop: 均方根传播优化器,用于优化深度神经网络

  • Adagrad: 自适应梯度下降优化器,用于优化稀疏数据和凸优化问题

  • Adadelta: 自适应学习率优化器,用于优化深度神经网络

  • Adam: 自适应矩估计优化器,用于优化深度神经网络

  • Adamax: Adam的变种,用于优化深度神经网络

  • Nadam: Nesterov-accelerated Adam的变种,用于优化深度神经网络

  • Ftrl: Follow-the-regularized-leader优化器,用于优化大规模线性模型

keras.losses

  • categorical_crossentropy: 多分类交叉熵损失函数,用于多分类问题

  • binary_crossentropy: 二分类交叉熵损失函数,用于二分类问题

  • mean_squared_error: 均方误差损失函数,用于回归问题

  • mean_absolute_error: 平均绝对误差损失函数,用于回归问题

  • mean_absolute_percentage_error: 平均绝对百分比误差损失函数,用于回归问题

  • mean_squared_logarithmic_error: 均方对数误差损失函数,用于回归问题

  • hinge: hinge损失函数,用于支持向量机

  • squared_hinge: 平方hinge损失函数,用于支持向量机

  • categorical_hinge: 多分类hinge损失函数,用于多分类支持向量机

  • logcosh: 对数双曲余弦损失函数,用于回归问题

  • kullback_leibler_divergence: KL散度损失函数,用于度量两个概率分布之间的差异

  • poisson: 泊松损失函数,用于计数问题

  • cosine_similarity: 余弦相似度损失函数,用于度量两个向量之间的相似度

keras.metrics

  • accuracy: 用于计算分类准确率

  • binary_accuracy: 用于计算二分类准确率

  • categorical_accuracy: 用于计算多分类准确率

  • sparse_categorical_accuracy: 用于计算稀疏多分类准确率

  • top_k_categorical_accuracy: 用于计算前k个预测中是否包含正确答案的准确率

  • sparse_top_k_categorical_accuracy: 用于计算稀疏多分类问题中前k个预测中是否包含正确答案的准确率

  • precision: 用于计算精确率

  • recall: 用于计算召回率

  • binary_crossentropy: 用于计算二分类交叉熵

  • categorical_crossentropy: 用于计算多分类交叉熵

  • sparse_categorical_crossentropy: 用于计算稀疏多分类交叉熵

  • mean_squared_error: 用于计算均方误差

  • mean_absolute_error: 用于计算平均绝对误差

  • mean_absolute_percentage_error: 用于计算平均绝对百分比误差

  • mean_squared_logarithmic_error: 用于计算均方对数误差

  • cosine_similarity: 用于计算余弦相似度

keras.utils

  • to_categorical: 将整型标签转换为one-hot编码

  • plot_model: 可视化模型结构

  • get_file: 下载并缓存文件

  • multi_gpu_model: 多GPU并行训练模型

  • Sequence: 用于生成批量数据的基类

  • HDF5Matrix: 用于从HDF5文件中读取数据

  • Progbar: 用于显示训练进度条的类

  • normalize: 将数据归一化到0-1范围

  • deserialize_keras_object: 从JSON字符串中反序列化Keras对象

  • serialize_keras_object: 将Keras对象序列化为JSON字符串

keras.callbacks

  • EarlyStopping: 用于提前停止训练,防止过拟合

  • ModelCheckpoint: 用于保存模型的权重和结构

  • ReduceLROnPlateau: 用于动态调整学习率,加速收敛

  • CSVLogger: 用于将训练日志写入CSV文件

  • TensorBoard: 用于可视化训练过程和模型结构

  • LearningRateScheduler: 用于动态调整学习率,加速收敛

  • TerminateOnNaN: 用于在出现NaN值时停止训练

  • RemoteMonitor: 用于将训练日志发送到远程服务器

  • LambdaCallback: 用于自定义回调函数

keras.preprocessing

  • image: 包含了一些常用的图像处理工具,如ImageDataGenerator、load_img等。

  • sequence: 包含了一些常用的序列处理工具,如TimeseriesGenerator等。

  • text: 包含了一些常用的文本处理工具,如Tokenizer、text_to_word_sequence等。

  • utils: 包含了一些常用的工具函数,如pad_sequences等。

keras.applications

  • VGG16: 包含16层卷积神经网络的预训练模型,用于图像分类和特征提取

  • VGG19: 包含19层卷积神经网络的预训练模型,用于图像分类和特征提取

  • ResNet50: 包含50层残差网络的预训练模型,用于图像分类和特征提取

  • InceptionV3: 包含48层卷积神经网络的预训练模型,用于图像分类和特征提取

  • InceptionResNetV2: 包含572层卷积神经网络的预训练模型,用于图像分类和特征提取

  • MobileNet: 轻量级卷积神经网络的预训练模型,用于移动设备和嵌入式设备上的图像分类和特征提取

  • DenseNet: 包含多个密集连接块的预训练模型,用于图像分类和特征提取

  • NASNet: 由神经结构搜索算法自动设计的预训练模型,用于图像分类和特征提取

keras.backend

  • tensorflow_backend: Keras的TensorFlow后端,用于在TensorFlow上运行Keras模型

  • theano_backend: Keras的Theano后端,用于在Theano上运行Keras模型

  • cntk_backend: Keras的CNTK后端,用于在CNTK上运行Keras模型

  • floatx: 默认的浮点数类型,可以设置为float16、float32或float64

  • set_floatx: 设置默认的浮点数类型

  • epsilon: 用于防止除以0的小量值

  • set_epsilon: 设置防止除以0的小量值

  • image_data_format: 图像数据的格式,可以设置为channels_first或channels_last

  • set_image_data_format: 设置图像数据的格式

  • clear_session: 清除当前会话中的所有Keras模型

  • manual_variable_initialization: 是否手动初始化变量

  • cast_to_floatx: 将输入数据转换为默认的浮点数类型

  • is_keras_tensor: 判断一个张量是否为Keras张量

  • get_uid: 获取一个唯一的字符串ID

  • print_tensor: 打印张量的值

  • gradients: 计算张量的梯度

  • stop_gradient: 停止计算某个张量的梯度

  • square: 计算张量的平方

  • abs: 计算张量的绝对值

  • sqrt: 计算张量的平方根

  • exp: 计算张量的指数函数

  • log: 计算张量的自然对数

  • round: 计算张量的四舍五入值

  • sign: 计算张量的符号函数

  • pow: 计算张量的幂函数

  • maximum: 计算张量的元素最大值

  • minimum: 计算张量的元素最小值

  • sin: 计算张量的正弦值

  • cos: 计算张量的余弦值

  • tan: 计算张量的正切值

  • dot: 计算张量

keras.preprocessing.image

  • ImageDataGenerator: 用于生成经过数据增强的图像数据,增加数据量,防止过拟合

  • load_img: 用于加载图像文件,并将其转换为PIL图像对象

  • img_to_array: 用于将PIL图像对象转换为NumPy数组

  • array_to_img: 用于将NumPy数组转换为PIL图像对象

  • apply_transform: 用于对图像进行随机变换,如旋转、平移、缩放等

  • random_rotation: 用于对图像进行随机旋转

  • random_shift: 用于对图像进行随机平移

  • random_shear: 用于对图像进行随机错切变换

  • random_zoom: 用于对图像进行随机缩放

  • random_channel_shift: 用于对图像进行随机通道偏移

  • random_brightness: 用于对图像进行随机亮度调整

  • random_contrast: 用于对图像进行随机对比度调整

  • random_flip: 用于对图像进行随机翻转

  • smart_resize: 用于对图像进行智能缩放,保持长宽比不变

keras.preprocessing.sequence

  • TimeseriesGenerator: 用于生成时间序列数据的批量数据,用于时间序列预测和回归分析

  • pad_sequences: 用于将序列数据填充到相同的长度,以便于进行批量处理

  • skipgrams: 用于生成skip-gram模型的训练数据,用于词向量学习

  • make_sampling_table: 用于生成负采样表,用于skip-gram模型的训练

  • make_sequence_matrix: 用于将序列数据转换为矩阵形式,以便于进行神经网络训练

keras.preprocessing.text

  • Tokenizer: 用于将文本转换为序列,生成词汇表,将文本转换为数字序列

  • text_to_word_sequence: 用于将文本转换为单词列表

  • one_hot: 用于将文本转换为one-hot编码

  • hashing_trick: 用于将文本转换为固定长度的数字序列

  • pad_sequences: 用于将序列数据填充到相同的长度,以便于进行批量处理

keras.preprocessing.utils

  • to_categorical: 将整型标签转换为one-hot编码

  • plot_model: 可视化模型结构

  • get_file: 下载并缓存文件

  • multi_gpu_model: 多GPU并行训练模型

  • Sequence: 用于生成批量数据的基类

  • HDF5Matrix: 用于从HDF5文件中读取数据

  • Progbar: 用于显示训练进度条的类

  • normalize: 将数据归一化到0-1范围

  • deserialize_keras_object: 从JSON字符串中反序列化Keras对象

  • serialize_keras_object: 将Keras对象序列化为JSON字符串

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
社会演员多的头像社会演员多普通用户
上一篇 2023年12月1日
下一篇 2023年12月1日

相关推荐