原标题:快速使用 Tensorflow 读取 7 万数据集!
作者 | 郭俊麟
责编 | 胡巍巍
Brief 概述
这篇文章中,我们使用知名的图片数据库「THE MNIST DATABASE」作为我们的图片来源,它的数据内容是一共七万张28×28像素的手写数字图片。
并被分成六万张训练集与一万张测试集,其中训练集里面,又有五千张图片被用来作为验证使用,该数据库是公认图像处理的 "Hello World" 入门级别库,在此之前已经有数不清的研究,围绕着这个模型展开。
不过初次看到这个库之后,肯定是对其长相产生许多的疑问,我们从外观上既看不到图片本身,也看不到任何的索引线索,他就是四个压缩包分别名称如下图:
对数据库以此方法打包的理由需要从计算机对数据的运算过程和内存开始说起,人类直观的图像是眼睛接收的光信号,这些不同颜色的光用数据的方式储存起来后有两种主要的格式与其对应的格式内容:
.jpeg: height, width, channels;
.png : height, width, channels, alpha。
(注意: .png 储存格式的图片含有透明度的信息,在处理图片的时候可以舍弃。)
这些图像使用模块如opencv导入到 python 中后,是以列表的方式呈现排列的数据,并且每次令image = cv2.imread()这类方式把数据指向到一个 image物件时。
都是把数据存入内存的一个过程,在内存里面的数据好处是可以非常快速的调用并处理,直到这个状态我们才算布置完数据被丢进算法前的状态。
然而,图像数据导入内存的转换并不是那么的迅捷,首先必须先解析每个像素的坐标和颜色值,再把每一次读取到的图片数据值合起来后,放入缓存中。
这样的流程在移动和读取上都显然没有优势,因此我们需要把数据回归到其最基本的本质 「二进制」 上。
Binary Data 二进制数据
Reasons for using binary data,使用二进制数据的理由
如果我们手上有成批的图片数据,把它们传入算法中算结果的过程,就好比一个人爬上楼梯,坐上滑水道的入口,等待经历一段未知的短暂旅程。
滑水道有很多个通道,一次可以让假设五个人准备滑下,而这时候如果后面递补的人速度不够快,就会造成该入口一定时间的空缺,直接导致效率地下。
而这个比喻中的滑水道入口,代表的是深度学习 GPU 计算端口,准备下滑的人代表数据本身,而我们现在需要优化的,就是如何让 GPU 在还没处理完这一个数据之前,就已经为它准备好下一批预处理数据。
让 GPU 永远保持工作状态可以进一步提升整体运算的效率,方法之一就是让数据回归到 「二进制」 的本质。
二进制是数据在电脑硬盘储存状态的原貌,也是数据被处理时,最本质的状态,因此批量图片数据第一件要被处理的事情就是让他们以二进制的姿态被放入到内存中。
此举就好比排队玩滑水道的人们都要事前把鞋子手表眼睛脱掉,带着最需要的东西上去排队后,等轮到自己时,一屁股坐上去摆好姿势后就可以开始,没有其他的冗余动作拖慢时间。
而我选择的入门数据库 MNIST 已经很贴心的帮我们处理好预处理的部分,分为四个类别:
测试集图像数据: t10k-images-idx3-ubyte.gz;
测试集图像标签: t10k-labels-idx1-ubyte.gz;
训练集图像数据: train-images-idx3-ubyte.gz;
训练集图像标签: train-labels-idx1-ubyte.gz。
图像识别基本上都是属于机器学习中的监督学习门类,因此四个类别其中两个是对应图片集的标签集,都是使用二进制的方法保存档案。
The approach to load images 读取数据的方法
既然知道了数据库里面的结构是二进制数据,接下来就可以使用 python 里面的模块包解析数据,压缩文件为 .gz 因此对应到打开此文件类型的模块名为 gzip,代码如下:
import gzip, os
import numpy as np
location = input('The directory of MNIST dataset: ')
path= os.path.join(location, 'train-images-idx3-ubyte.gz')
try:
with gzip.open(path, 'rb') as fi:
data_i = np.frombuffer(fi.read(), dtype=np.int8, offset=16)
images_flat_all = data_i.reshape(-1, 784)
print(images_flat_all)
print('----- Separation -----')
print('Size of images_flat: ', len(images_flat_all))
except:
print("The file directory doesn't exist!")
### ----- Result is shown below ----- ###
The directory of MNIST dataset: /home/abc/MNIST_data
[[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
...
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]
[0 0 0 ... 0 0 0]]
----- Separation -----
Size of images_flat: 60000
path_label = os.path.join(location, 'train-labels-idx1-ubyte.gz')
with gzip.open(path_label, 'rb') as fl:
data_l = np.frombuffer(fl.read(), dtype=np.int8, offset=8)
print(data_l)
print('----- Separation -----')<