python处理MNIST数据集

这篇博客详细介绍了MNIST手写数字数据集,包括数据集获取、二进制文件存储格式、如何使用Python访问文件内容以及如何将数据集保存为.jpg图片格式。文章通过解析训练集图像和标签文件,展示了数据结构并提供了转换图片的示例。
摘要由CSDN通过智能技术生成

1. MNIST数据集

1.1 MNIST数据集获取

MNIST数据集是入门机器学习/模式识别的最经典数据集之一。最早于1998年Yan Lecun在论文:

中提出。经典的LeNet-5 CNN网络也是在该论文中提出的。
数据集包含了0-9共10类手写数字图片,每张图片都做了尺寸归一化,都是28x28大小的灰度图。每张图片中像素值大小在0-255之间,其中0是黑色背景,255是白色前景。如下图所示:


MNIST共包含70000张手写数字图片,其中有60000张用作训练集,10000张用作测试集。原始数据集可在MNIST官网下载。

下载之后得到4个压缩文件:

train-images-idx3-ubyte.gz #60000张训练集图片
train-labels-idx1-ubyte.gz #60000张训练集图片对应的标签
t10k-images-idx3-ubyte.gz #10000张测试集图片
t10k-labels-idx1-ubyte.gz #10000张测试集图片对应的标签

将其解压,得到

train-images-idx3-ubyte
train-labels-idx1-ubyte
t10k-images-idx3-ubyte
t10k-labels-idx1-ubyte
1.2 MNIST二进制文件的存储格式

解压得到的四个文件都是二进制格式,我们如何获取其中的信息呢?这得首先了解MNIST二进制文件的存储格式(官网底部有介绍),以训练集图像文件train-images-idx3-ubyte为例:

图像文件的

  • 第1-4个byte(字节,1byte=8bit),即前32bit存的是文件的magic number,对应的十进制大小是2051;
  • 第5-8个byte存的是number of images,即图像数量60000;
  • 第9-12个byte存的是每张图片行数/高度,即28;
  • 第13-16个byte存的是每张图片的列数/宽度,即28。
  • 从第17个byte开始,每个byte存储一张图片中的一个像素点的值。

因为train-images-idx3-ubyte文件总共包含了60000张图片数据,按照以上的存储方式,我们算一下该文件的大小:

  • 一张图片包含28x28=784个像素点,需要784bytes的存储空间;
  • 60000张图片则需要784x60000=47040000 bytes的存储空间;
  • 此外,文件开始处使用了16个bytes用于存储magic number、图像数量、图像高度和图像宽度,因此,训练集图像文件的大小应该是47040000+16=47040016 bytes。

我们查看解压后的train-images-idx3-ubyte文件的属性:

文件实际大小和我们计算的结果一致。

类似地,我们查看训练集标签文件train-labels-idx1-ubyte的存储格式:

和图像文件类似:

  • 第1-4个byte存的是文件的magic number,对应的十进制大小是2049;
  • 第5-8个byte存的是number of items,即label数量60000;
  • 从第9个byte开始,每个byte存一个图片的label信息,即数字0-9中的一个。

计算一下训练集标签文件train-labels-idx1-ubyte的文件大小:

  • 1x60000+8=60008 bytes。

与该文件实际的大小一致:


另外两个文件,即测试集图像文件、测试集标签文件的存储方式和训练图像文件、训练标签文件相似,只是图像数量由60000变为10000。

1.3 使用python访问MNIST数据集文件内容

知道了MNIST二进制文件的存储方式,下面介绍如何使用python访问文件内容。同样以训练集图像文件train-images-idx3-ubyte为例:

首先,使用open()函数打开文件,并使用read()方法将所有的文件数据读入到一个字符串中:

yan@yanubuntu:~/codes/Deep-Learning-21-Examples/chapter_1/MNIST_data$ python
Python 2.7.12 (default, Nov 12 2018, 14:36:49) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> with open('train-images.idx3-ubyte', 'rb') as f:
...  file = f.read()
... 
>>> 

file是str类型,其中的每个元素就存储的1个字节的内容。我们现在查看前4个字节,即magic number的内容,看下是否是前面说的2051:

>>> magic_number=file[:4]
>>> magic_number
'\x00\x00\x08\x03'
>>> magic_number.encode('hex')
'00000803'
>>> int(magic_number.encode('hex'),16)
2051

可以看出前4个byte的值确实是2051,但是不能直接输出magic number的内容,需要将其编码,然后才能转成十进制的int类型(有关字节编码的知识暂时没懂,先用着)。
同样的方式,查看图像数量、图像高度和图像宽度信息:

>>> num_images = int(file[4:8].encode('hex'),16)
>>> num_images
60000
>>> h_image = int(file[8:12].encode('hex'),16)
>>> h_image
28
>>> w_image = int(file[12:16].encode('hex'),16)
>>> w_image
28

现在获取第1张图片的像素信息,然后利用numpy和cv2模块转换其格式,并保存成.jpg格式的图片:

>>> image1 = [int(item.encode('hex'), 16) for item in file[16:16+784]]
>>> len(image1)
784
>>> import numpy as np
>>> import cv2
>>> image1_np = np.array(image1, dtype=np.uint8).reshape(28,28,1)
>>> image1_np.shape
(28, 28, 1)
>>> cv2.imwrite('image1.jpg', image1_np)
True
>>> 

保存下来的图片image1.jpg如下图所示:

该图片的标签是5,我们可以验证一下训练集标签文件train-labels-idx1-ubyte文件的第一个标签是否和图像内容一一对应:

>>> with open('train-labels.idx1-ubyte', 'rb') as f:
...  label_file = f.read()
... 
>>> label1 = int(label_file[8].encode('hex'), 16)
>>> label1
5
>>> 

训练标签文件的第一张图片标签是第9个byte(索引从0开始,所以第9个byte是label_file[8]),结果没问题。

1.4 将MNIST数据集保存成.jpg图片格式

因为使用上面得到的file和label_file文件是str类型,因此可以使用迭代的方式,将所有训练和测试集的二进制文件格式转成.jpg图片格式。转换脚本mnist2jpg.py如下:

# coding=utf-8
'''将二进制格式的MNIST数据集转成.jpg图片格式并保存,图片标签包含在图片名中'''
import numpy as np
import cv2
import os

def save_mnist_to_jpg(mnist_image_file, mnist_label_file, save_dir):
if ‘train’ in os.path.basename(mnist_image_file):
num_file = 60000
prefix = ‘train’
else:
num_file = 10000
prefix = ‘test’
with open(mnist_image_file, ‘rb’) as f1:
image_file = f1.read()
with open(mnist_label_file, ‘rb’) as f2:
label_file = f2.read()
image_file = image_file[16:]
label_file = label_file[8:]
for i in range(num_file):
label = int(label_file[i].encode(‘hex’), 16)
image_list = [int(item.encode(‘hex’), 16) for item in image_file[i784:i784+784]]
image_np = np.array

  • 1
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值