目录
0. 写作目的
好记性不如烂笔头。
1. 前言
对于较小的数据处理时,我们可以完全读入内存,但是针对较大的数据集,如果一次性读入内存,将会出现一下两点问题:
1) 内存是否够用。
一些较大的数据集,如ImageNet数据集,一次性完全读入内存,需要较大的内存,即使内存足够,我们也不会使用该方法,原因如下第二点。
2) 程序的交互性差
如果我们将较大的数据集一次性读入时,首先在程序运行之前,我们第一步就要读入数据,如果在读入数据后,后面的代码出现了bug,修改bug后,仍需要较大的时间读入,浪费时间。(虽然对于Jupyter notebook或类似的环境修改一下代码,可以避免重新读入,但是读入的过程的仍在浪费时间,而且即使数据全都读入内存,但在一段时间内我们使用的数据仍只是一部分,因此对于内存也造成了一种资源浪费。)
因此,一种较好的方式就是,即用即读。在深度框架中,不同的深度学习框架都有自己的序列化格式,如caffe的LMDB文件,Tensorflow的TFrecord文件等。
在之前使用Caffe的LMDB文件时,我就有一种想法,以图像分类为例,可不可以先保存图像的路径,以及对应的标签,然后在使用时,进行即用即读。本文首先进行了该种方法的尝试。
2. 即用即读的训练方式
2.1 数据的准备
首先下载MNIST的数据,如果下载的不是图像数据集,是train-images-idx3-ubyte.gz,在ubuntu下采用命令:gunzip train-images-idx3-ubyte.gz进行解压,然后通过以下代码[1](基于PyTorch的)来生成图像数据集。以下代码需要在数据目录下运行,运行结果将在数据集目录下,产生两个图像文件夹train和test,同时生成两个txt文件——train.txt 和test.txt,其中图像文件为所有图像,txt的内容是:图像的绝对路径以及对应的标签。
import os
from skimage import io
import torchvision.datasets.mnist as mnist
root=os.getcwd()
train_set = (
mnist.read_image_file(os.path.join(root, 'train-images-idx3-ubyte')),
mnist.read_label_file(os.path.join(root, 'train-labels-idx1-ubyte'))
)
test_set = (
mnist.read_image_file(os.path.join(root, 't10k-images-idx3-ubyte')),
mnist.read_label_file(os.path.join(root, 't10k-labels-idx1-ubyte'))
)
print("training set :",train_set[0].size())
print("test set :",test_set[0].size())
def convert_to_img(train=True):
if(train):
f=open(root+'/train.txt','w')
data_path=root+'/train/'
if(not os.path.exists(data_path)):
os.makedirs(data_path)
for i, (img,label) in enumerate(zip(train_set[0],train_set[1])):
img_path=data_path+str(i)+'