gluon模塊進行數據加載-Dataset和DataLoader


在gluon接口中,通過Dataset和DataLoader來對數據集進行循環遍歷,並返回batch大小的數據,其中Dataset對象用於數據的收集、加載和變換,而DataLoader對象用於返回batch大小的數據。

1. 相關模塊
mxnet.gluon.data : 數據加載API
mxnet.gluon.data.vision : 專門用於計算機視覺的數據集API和處理工具
2. Dataset介紹
Dataset對象用於收集數據、加載和變換數據,其中 數據加載是能夠通過給定的下標獲取對應的樣本,數據變換可以對數據進行各種數據增廣操作

原理
所有Dataset類中,都有以下四個方法:

getitem(idx): 數據加載,用於返回第idx個樣本
len(): 用於返回數據集的樣本的數量
transform(fn, lazy = True): 數據變換,用於返回對每個樣本利用fn函數進行數據變換(增廣)后的Dataset
transform_first(fn, lazy = True): 數據變換,用於返回對每個樣本的特征利用fn函數進行數據變換(增廣)后的Dataset,而不對label進行數據增廣
用法
ArrayDataset

import mxnet as mx
## 定義
mx.random.seed(42) # 固定隨機數種子,以便能夠復現
X = mx.random.uniform(shape = (10, 3))
y = mx.random.uniform(shape = (10, 1))
dataset = mx.gluon.data.ArrayDataset(X, y) # ArrayDataset不需要從硬盤上加載數據
## 使用
dataset[5]  # 將返回第6個樣本的特征和標簽,(特征,標簽)

ImageFolderDataset

import mxnet as mx
## 定義
dataset= gdata.vision.ImageFolderDataset("樣本集的根路徑", flag=1)
## 使用
dataset[5]  # 將返回第6個樣本的特征和標簽,(特征,標簽)

ImageRecordDataset

import mxnet as mx
## 定義
file = '/xxx/train.rec'
 #不需要指定idx文件路徑,會從路徑中自動拼接處idx的路徑,例如此處為/xxx/train.idx
dataset= gdata.vision.ImageRecordDataset(file) 
## 使用
dataset[5]  # 將返回第6個樣本的特征和標簽,(特征,標簽)

API中的所有Dataset


mxnet.gluon.data.Dataset: 抽象的數據集類

mxnet.gluon.data.ArrayDataset: 組合多個Dataset的數據集類

mxnet.gluon.data.RecordFileDataset: .rec文件的數據集類

mxnet.gluon.data.vison.MNIST: MNIST數據集的Dataset

mxnet.gluon.data.vison.FashionMNIST: FashionMNIST數據集的Dataset

mxnet.gluon.data.vison.CIFAR10: CIFAR10數據集的Dataset

mxnet.gluon.data.vison.CIFAR100: CIFAR100數據集的Dataset

mxnet.gluon.data.vison.ImageRecordDataset: 含有圖片的.rec文件的Dataset

mxnet.gluon.data.vison.ImageFolderDataset: 存儲圖片在文件夾結構的Dataset

說明: mxnet和numpy的array可以直接作為Dataset

3. DataLoader介紹
加載Dataset,迭代時返回batch大小的樣本
可以方便的並行地加載數據
使用示例如下:

from multiprocessing import cpu_count
CPU_COUNT = cpu_count()
data_loader = mx.gluon.data.DataLoader(dataset, batch_size = 5, num_workers = CPU_COUNT)
for X, y in data_loader:
    print X.shape, y.shape

4. transforms模塊介紹
在gloun的data接口中,有可以使用的數據增廣的模塊(mxnet.gluon.data.vision.tranforms)。在transforms模塊中定義了很多數據變換的layer(為Block的子類),變換layer的輸入為樣本,輸出為變換后的樣本。

用法示例

from mxnet.gluon import data as gdata
train_ds = gdata.vision.ImageFolderDataset("樣本集的根路徑", flag=1)
print train_ds[0] #變換之前的數據
## 數據變換定義
transform_train = gdata.vision.transforms.Compose([  # Compose將這些變換按照順序連接起來
        # 將圖片放大成高和寬各為 40 像素的正方形。
        gdata.vision.transforms.Resize(40),
        # 隨機對高和寬各為 40 像素的正方形圖片裁剪出面積為原圖片面積 0.64 到 1 倍之間的小正方
        # 形,再放縮為高和寬各為 32 像素的正方形。
        gdata.vision.transforms.RandomResizedCrop(32, scale=(0.64, 1.0),
                                                  ratio=(1.0, 1.0)),
        # 隨機左右翻轉圖片。
        gdata.vision.transforms.RandomFlipLeftRight(),
        # 將圖片像素值按比例縮小到 0 和 1 之間,並將數據格式從“高 * 寬 * 通道”改為“通道 * 高 * 寬”。
        gdata.vision.transforms.ToTensor(),
        # 對圖片的每個通道做標准化。
        gdata.vision.transforms.Normalize([0.4914, 0.4822, 0.4465],
                                          [0.2023, 0.1994, 0.2010])
    ])

train_ds_transformed = train_ds.transform_first(train_ds )
print  train_ds_transformed[0] #變換之后的數據

重要的變換

  • Cast: 變換數據類型
  • ToTensor: 將圖像數組由“高 * 寬 * 通道”改為 “通道 * 高 * 寬”
  • Normalize: 對圖片(shape為通道 * 高 * 寬)每個通道上的每個像素按照均值和方差標准化
  • RandomResizedCrop: 首先按照一定的比例隨機裁剪圖像,然后再對圖像變換高和寬
  • Resize: 將圖像變換高和寬
  • RandomFlipLeftRight: 隨機左右翻轉

例子

# coding: utf-8
from mxnet.gluon import data as gdata
import multiprocessing
import os

def get_cifar10(root_dir,  batch_size, num_workers =  1):
    train_ds = gdata.vision.ImageFolderDataset(os.path.join(root_dir, 'train'), flag=1)
    valid_ds = gdata.vision.ImageFolderDataset(os.path.join(root_dir, 'valid'), flag=1)
    train_valid_ds = gdata.vision.ImageFolderDataset(os.path.join(root_dir, 'train_valid'), flag=1)
    test_ds = gdata.vision.ImageFolderDataset(os.path.join(root_dir, 'test'), flag=1)

    transform_train = gdata.vision.transforms.Compose([
        # 將圖片放大成高和寬各為 40 像素的正方形。
        gdata.vision.transforms.Resize(40),
        # 隨機對高和寬各為 40 像素的正方形圖片裁剪出面積為原圖片面積 0.64 到 1 倍之間的小正方
        # 形,再放縮為高和寬各為 32 像素的正方形。
        gdata.vision.transforms.RandomResizedCrop(32, scale=(0.64, 1.0),
                                                  ratio=(1.0, 1.0)),
        # 隨機左右翻轉圖片。
        gdata.vision.transforms.RandomFlipLeftRight(),
        # 將圖片像素值按比例縮小到 0 和 1 之間,並將數據格式從“高 * 寬 * 通道”改為
        # “通道 * 高 * 寬”。
        gdata.vision.transforms.ToTensor(),
        # 對圖片的每個通道做標准化。
        gdata.vision.transforms.Normalize([0.4914, 0.4822, 0.4465],
                                          [0.2023, 0.1994, 0.2010])
    ])

    # 測試時,無需對圖像做標准化以外的增強數據處理。
    transform_test = gdata.vision.transforms.Compose([
        gdata.vision.transforms.ToTensor(),
        gdata.vision.transforms.Normalize([0.4914, 0.4822, 0.4465],
                                          [0.2023, 0.1994, 0.2010])
    ])
    train_ds = train_ds.transform_first(transform_train)
    valid_ds = valid_ds.transform_first(transform_test)
    train_valid_ds = train_valid_ds.transform_first(transform_train)
    test_ds = test_ds.transform_first(transform_test)
    train_data = gdata.DataLoader(train_ds, batch_size, shuffle=True, last_batch='keep',num_workers = num_workers)
    valid_data = gdata.DataLoader(valid_ds, batch_size, shuffle=False, last_batch='keep', num_workers = num_workers)
    train_valid_data = gdata.DataLoader(train_valid_ds, batch_size, shuffle=True, last_batch='keep', num_workers=num_workers)
    test_data = gdata.DataLoader(test_ds, batch_size, shuffle=False, last_batch='keep', num_workers=num_workers)
    return train_data, valid_data, train_valid_data, test_data


if __name__ == '__main__':
    batch_size = 256
    root_dir =  '/home/face/common/samples/cifar-10/train_valid_test'

    train_data, valid_data, train_valid_data, test_data = get_cifar10(root_dir, batch_size)

    for batch in train_data:
        data, label = batch
        print data.shape, label

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM