深度学习初学者指南
上QQ阅读APP看书,第一时间看更新

3.1.2 二值化MINST数据集

MNIST数据集在深度学习领域非常有名(Deng,L.,2012),它是由数千张手写数字图像组成的。图3.1给出了MNIST数据集的8个样本。

如你所见,这个数据集中的样本是凌乱的,但是非常真实。每个图像的大小都是像素。只有10个目标类,每个目标类分别对应中的某个数字。这里的复杂之处通常在于一些数字看起来与其他数字很相似,例如,1和7,或者0和6。然而,大多数深度学习算法都成功地解决了对这种数据集的高精度分类问题。

图3.1 MNIST数据集的八个样本。每个图像顶部的数字对应于目标类

如果仔细观察图3.1中的样本,就会发现这些值并不完全是0和1,即二元的。事实上,图像是8位的灰度,范围为[0,255]。如前所述,对于大多数高级深度学习算法来说,这不再是一个问题。然而,对于一些算法,例如受限玻尔兹曼机(RBM),输入数据需要以二元格式[0,1]出现,因为那是算法的传统工作方式。

因此,我们将做下列两件事情:

·对图像进行二值化,得到二元输入。

·对目标进行二值化,使之成为二元分类问题。

对于本例,我们将随意选择两个数字,7和8,将它们作为目标类。

1.二值化图像

二值化是图像处理中的常见步骤。它的正式名称是图像阈值,因为我们需要一个阈值来决定哪些值变成0或者1。关于这个主题的完整介绍,请查阅(Sezgin,M.,and Sankur,B.,2004)。这就是说,在选择将变化范围从[0,255]降到[0,1]的完美阈值背后有一套科学。

但是,由于本书不是关于图像处理的教材,所以随机地将阈值设置为128。因此,任何低于128的值将变成0,任何大于或等于128的值将变成1。

这一步可以通过在Python中使用索引轻松完成。为了继续下去,将显示数据集的一小部分,以确保数据被正确转换。在接下来的步骤中,将通过执行下列命令来实现这个效果:

1)要加载数据集并验证其维度(形状),运行以下命令:

输出如下所示:

首先要注意的是,我们正在使用的机器学习库在Python中称为scikit learn或sklearn,它是一种最常用的通用机器学习库。我们使用fetch_openml()方法加载MNIST数据集,该方法需要一个表示要加载数据集标识符的参数,在本例中为'mnist_784'。数字784源于MNIST图像的大小,它是28×28像素,可以将该图像解释为784个元素组成的向量,而不是28列28行的矩阵。通过验证shape属性,可以发现数据集有7万幅图像,使用大小为784的向量表示,目标(标签)数据具有相同的比例。

请注意,与上一节使用加载到pandas的数据集不同,在本例中,我们直接将数据作为列表或列表的数组。你应该熟悉操作pandas和原始数据集。

2)要验证数据进行二值化之前和之后的效果对比,可以运行下列命令:

输出结果如下:

指令data[0].reshape(28,28)[10:18,10:18]做了三件事:

1)data[0]以一个大小为(1,784)的数组形式返回第一张图像。

2)reshape(28,28)将(1,784)数组调整为(28,28)矩阵,即实际图像。这对于显示实际数据非常有用,例如生成图3.1。

3)[10:18,10:18]只取(28,28)矩阵的一个子集,列和行位置都是10到18,这或多或少与图像的中心区域相对应,是观察变化的好地方。

前面的代码仅用于查看数据,但实际的更改将在下一行中完成。代码行mnist.data[mnist.data<128]=0使用Python索引。指令mnist.data<128返回一个多维的布尔值数组,其中mnist.data[]作为索引,将其值设置为0。关键是对所有严格小于128的值都这样操作。下一行代码将进行同样的操作,但它是对大于或等于128的值进行操作。

通过检查输出,可以确认数据已经成功更改,并且已经设置了阈值或进行了二值化。

2.二值化目标数据

我们将通过下列两个步骤二值化目标数据:

1)首先,我们将丢弃其他数字的图像数据,只保留7和8。然后将7映射到0,8映射到1。这些命令将创建新的变量X和y,只包含数字7和8:

输出结果如下:

请注意OR操作符|的使用,它在逻辑上取两组布尔索引,并使用OR操作符进行组合。这些索引用于生成新的数据集。新数据集包含14 000多张图像。

2)要将7映射为0,将8映射为1,可以执行下列命令:

输出结果如下:

指令[0 if v=='7'else 1 for v in y]检查y中的每个元素,如果一个元素是'7',那么它返回0,否则(例如,当它是'8'时)返回1。正如输出所示,选择前10个元素后,目标数据被二值化为集合{0,1}。

请记住,y中的目标数据已经是二元数据了,因为它只有两种可能的唯一取值{7,8}。但是我们通常把它变成二元集合{0,1},因为当使用不同的深度学习算法来计算特定类型的损失函数时,这样会更好。

这样,数据集就可以与二元通用分类器一起使用了。但是,如果我们实际上想拥有多个类别,例如,检测所有MNIST数据集的10位而不仅是2位,那么该怎么办呢?或者,如果数据特征、列或输入不是数字的,而是类别属性呢?下一节将帮助你准备这些情况下的数据。