<>问题
在训练人脸数据集MS1M时,采用pytorch的ImageFolder
对原始的图像进行的读取。由于人脸数据小,且量大,导致GPU很快训练完成,但是IO却很慢,从而拖垮了整个训练时间。
 <>解决方法
以上问题的根本原因在于pytorch没有自己的数据格式,像TF的TFrecorde,mx的rec文件以及caffe使用lmdb,都有自己的格式。因此,我们可以采用其他框架的格式做数据读取,pytorch来做训练。
 * 
其中由于我自己一直不喜欢用tf的TFrecorde(早期学tf时也不喜欢),mx的与torch很相似,lmdb虽然可以不依赖框架使用,但是需要自己掌握的很好,这里只介绍有关自己使用mx的rec
 <>步骤
首先压缩问题:在mxnet的github的网站下载源码文件,其中tools的img2rec.py即官网给的编码文件
图像文件夹如下形式:
 imgs
 * id1---->images
 * id2---->images 
首先生成.lst文件,该文件包含了图像的所有路径。执行代码
python img2rec.py train_data imgs --list --recursive --num-thread=10 
 * train_data为.lst文件的名称
 * imgs为包含图像的文件夹的路径
 * --list表示生成.lst文件
 * --recursive表示浏览路径下的所有文件
 * --num-thread表示多线程,一定要设置,不然默认的1,会非常慢 
然后根据生成的.lst文件生成rec文件
执行代码
python img2rec train_data images --num-thread=10 
 * 此时 train_data依旧是.lst文件名
 * images为要生成的rec的文件名
 * 会生成两个文件 : images.rec和images.idx,这两个就是我们需要的文件 
正式的代码部分
 * 推荐使用mxnet的gluon这个封装好的模块 import mxnet as mx from mxnet.gluon.data.vision 
import ImageRecordDataset from mxnet.gluon.data import DataLoader import torch 
import numpy as np from PIL import Image def load_mx_rec(): data = 
ImageRecordDataset('F:/MXnet/train_data.rec') train_loader = DataLoader(data, 
batch_size=4, shuffle=False) train_transform = transforms.Compose([transforms.
Resize([int(128 * 128 / 112) , int(128 * 128 / 112)]), transforms.RandomCrop([
128, 128]) , transforms.RandomHorizontalFlip(), transforms.ToTensor()]) for 
input, label in iter(train_loader): inputs = input.asnumpy() nB = torch.rand(4, 
3, 128, 128) for i in range(4): image = Image.fromarray(inputs[i,:,:,:]) image =
 train_transform(image) nB[i,:,:,:] = image labels = label.asnumpy() labels = 
torch.from_numpy(labels).long() # load_mx_rec() import mxnet as mx from mxnet.
gluon.data.vision import ImageRecordDataset from mxnet.gluon.data import 
DataLoaderimport torch import numpy as np import cv2 def load_mx_rec_2(): data =
 ImageRecordDataset('F:/MXnet/train_data.rec') data1 = datasets.ImageFolder(
'F:/MXnet/images') train_loader = DataLoader(data, batch_size=4, shuffle=False) 
# train_transform = transforms.Compose([transforms.Resize([int(128 * 128 / 112) 
# , int(128 * 128 / 112)]), transforms.RandomCrop([128, 128]) # , 
transforms.RandomHorizontalFlip(), transforms.ToTensor()]) for input, label in 
iter(train_loader): inputs = input.asnumpy() nB = torch.rand(4, 3, 128, 128) for
 iin range(4): image = cv2.cvtColor(inputs[i,:,:,:], cv2.COLOR_RGB2BGR) size = (
int(128 * 128 / 112), int(128 * 128 / 112)) image = cv2.resize(image, size) x = 
np.random.randint(0, int(128*128/112)-128) y = np.random.randint(0, int(128*128/
112)-128) image = image[x:x+128, y:y+128] if random.choice([0,1])>0: cv2.flip(
image, 1, image) image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) image = image.
transpose(3, 1, 2).astype(np.float32) / 255 image[0,:,:] = (image[0,:,:] - 0.5) 
/ 0.5 image[1,:,:] = (image[1,:,:] - 0.5) / 0.5 image[2,:,:] = (image[2,:,:] - 
0.5) / 0.5 image = torch.from_numpy(image) nB[i,:,:,:] = image labels = label.
asnumpy() labels = torch.from_numpy(labels).long() load_mx_rec_2() 
 * 以上两个代码都可以实现我们所希望的功能
 * 代码1为了使用pytorch的transforms,中间转换到了PIL的格式,如果transforms很复杂,自己也不好用cv2实现,可以这样
 * 推荐使用代码2,利用cv2来替换transforms,效率更高一些。