1. 程式人生 > >Bunch 轉換為 HDF5 文件:高效存儲 Cifar 等數據集

Bunch 轉換為 HDF5 文件:高效存儲 Cifar 等數據集

scene sta hdf baidu nsh item bow none asa

關於如何將數據集封裝為 Bunch 可參考 關於 『AI 專屬數據庫的定制』的改進。

PyTables 是 Python 與 HDF5 數據庫/文件標準的結合。它專門為優化 I/O 操作的性能、最大限度地利用可用硬件而設計,並且它還支持壓縮功能。

下面的代碼均是在 Jupyter NoteBook 下完成的:

import sys 
sys.path.append(‘E:/xinlib‘)
from base.filez import DataBunch
import tables as tb
import numpy as np


def bunch2hdf5(root):
    ‘‘‘
    這裏我僅僅封裝了 Cifar10、Cifar100、MNIST、Fashion MNIST 數據集,
使用者還可以自己追加數據集。 ‘‘‘ db = DataBunch(root) filters = tb.Filters(complevel=7, shuffle=False) # 這裏我采用了壓縮表,因而保存為 `.h5c` 但也可以保存為 `.h5` with tb.open_file(f{root}X.h5c‘, ‘w‘, filters=filters, title=‘Xinet\‘s dataset‘) as h5: for name in db.keys(): h5.create_group(‘/‘
, name, title=f{db[name].url}) if name != ‘cifar100‘: h5.create_array(h5.root[name], ‘trainX‘, db[name].trainX, title=‘訓練數據‘) h5.create_array(h5.root[name], ‘trainY‘, db[name].trainY, title=‘訓練標簽‘) h5.create_array(h5.root[name], ‘testX‘, db[name].testX, title=
‘測試數據‘) h5.create_array(h5.root[name], ‘testY‘, db[name].testY, title=‘測試標簽‘) else: h5.create_array(h5.root[name], ‘trainX‘, db[name].trainX, title=‘訓練數據‘) h5.create_array(h5.root[name], ‘testX‘, db[name].testX, title=‘測試數據‘) h5.create_array(h5.root[name], ‘train_coarse_labels‘, db[name].train_coarse_labels, title=‘超類訓練標簽‘) h5.create_array(h5.root[name], ‘test_coarse_labels‘, db[name].test_coarse_labels, title=‘超類測試標簽‘) h5.create_array(h5.root[name], ‘train_fine_labels‘, db[name].train_fine_labels, title=‘子類訓練標簽‘) h5.create_array(h5.root[name], ‘test_fine_labels‘, db[name].test_fine_labels, title=‘子類測試標簽‘) for k in [‘cifar10‘, ‘cifar100‘]: for name in db[k].meta.keys(): name = name.decode() if name.endswith(‘names‘): label_names = np.asanyarray([label_name.decode() for label_name in db[k].meta[name.encode()]]) h5.create_array(h5.root[k], name, label_names, title=‘標簽名稱‘)

完成 BunchHDF5 的轉換

root = ‘E:/Data/Zip/‘
bunch2hdf5(root)
h5c = tb.open_file(‘E:/Data/Zip/X.h5c‘)
h5c
File(filename=E:/Data/Zip/X.h5c, title="Xinet‘s dataset", mode=‘r‘, root_uep=‘/‘, filters=Filters(complevel=7, complib=‘zlib‘, shuffle=False, bitshuffle=False, fletcher32=False, least_significant_digit=None))
/ (RootGroup) "Xinet‘s dataset"
/cifar10 (Group) ‘https://www.cs.toronto.edu/~kriz/cifar.html‘
/cifar10/label_names (Array(10,)) ‘標簽名稱‘
  atom := StringAtom(itemsize=10, shape=(), dflt=b‘‘)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘irrelevant‘
  chunkshape := None
/cifar10/testX (Array(10000, 32, 32, 3)) ‘測試數據‘
  atom := UInt8Atom(shape=(), dflt=0)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘irrelevant‘
  chunkshape := None
/cifar10/testY (Array(10000,)) ‘測試標簽‘
  atom := Int32Atom(shape=(), dflt=0)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘little‘
  chunkshape := None
/cifar10/trainX (Array(50000, 32, 32, 3)) ‘訓練數據‘
  atom := UInt8Atom(shape=(), dflt=0)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘irrelevant‘
  chunkshape := None
/cifar10/trainY (Array(50000,)) ‘訓練標簽‘
  atom := Int32Atom(shape=(), dflt=0)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘little‘
  chunkshape := None
/cifar100 (Group) ‘https://www.cs.toronto.edu/~kriz/cifar.html‘
/cifar100/coarse_label_names (Array(20,)) ‘標簽名稱‘
  atom := StringAtom(itemsize=30, shape=(), dflt=b‘‘)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘irrelevant‘
  chunkshape := None
/cifar100/fine_label_names (Array(100,)) ‘標簽名稱‘
  atom := StringAtom(itemsize=13, shape=(), dflt=b‘‘)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘irrelevant‘
  chunkshape := None
/cifar100/testX (Array(10000, 32, 32, 3)) ‘測試數據‘
  atom := UInt8Atom(shape=(), dflt=0)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘irrelevant‘
  chunkshape := None
/cifar100/test_coarse_labels (Array(10000,)) ‘超類測試標簽‘
  atom := Int32Atom(shape=(), dflt=0)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘little‘
  chunkshape := None
/cifar100/test_fine_labels (Array(10000,)) ‘子類測試標簽‘
  atom := Int32Atom(shape=(), dflt=0)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘little‘
  chunkshape := None
/cifar100/trainX (Array(50000, 32, 32, 3)) ‘訓練數據‘
  atom := UInt8Atom(shape=(), dflt=0)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘irrelevant‘
  chunkshape := None
/cifar100/train_coarse_labels (Array(50000,)) ‘超類訓練標簽‘
  atom := Int32Atom(shape=(), dflt=0)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘little‘
  chunkshape := None
/cifar100/train_fine_labels (Array(50000,)) ‘子類訓練標簽‘
  atom := Int32Atom(shape=(), dflt=0)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘little‘
  chunkshape := None
/fashion_mnist (Group) ‘https://github.com/zalandoresearch/fashion-mnist‘
/fashion_mnist/testX (Array(10000, 28, 28, 1)) ‘測試數據‘
  atom := UInt8Atom(shape=(), dflt=0)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘irrelevant‘
  chunkshape := None
/fashion_mnist/testY (Array(10000,)) ‘測試標簽‘
  atom := Int32Atom(shape=(), dflt=0)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘little‘
  chunkshape := None
/fashion_mnist/trainX (Array(60000, 28, 28, 1)) ‘訓練數據‘
  atom := UInt8Atom(shape=(), dflt=0)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘irrelevant‘
  chunkshape := None
/fashion_mnist/trainY (Array(60000,)) ‘訓練標簽‘
  atom := Int32Atom(shape=(), dflt=0)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘little‘
  chunkshape := None
/mnist (Group) ‘http://yann.lecun.com/exdb/mnist‘
/mnist/testX (Array(10000, 28, 28, 1)) ‘測試數據‘
  atom := UInt8Atom(shape=(), dflt=0)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘irrelevant‘
  chunkshape := None
/mnist/testY (Array(10000,)) ‘測試標簽‘
  atom := Int32Atom(shape=(), dflt=0)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘little‘
  chunkshape := None
/mnist/trainX (Array(60000, 28, 28, 1)) ‘訓練數據‘
  atom := UInt8Atom(shape=(), dflt=0)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘irrelevant‘
  chunkshape := None
/mnist/trainY (Array(60000,)) ‘訓練標簽‘
  atom := Int32Atom(shape=(), dflt=0)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘little‘
  chunkshape := None

從上面的結構可看出我將 Cifar10Cifar100MNISTFashion MNIST 進行了封裝,並且還附帶了它們各種的數據集信息。比如標簽名,數字特征(以數組的形式進行封裝)等。

%%time
arr = h5c.root.cifar100.trainX.read() # 讀取數據十分快速
Wall time: 125 ms
arr.shape
(50000, 32, 32, 3)
h5c.root
/ (RootGroup) "Xinet‘s dataset"
  children := [‘cifar10‘ (Group), ‘cifar100‘ (Group), ‘fashion_mnist‘ (Group), ‘mnist‘ (Group)]

X.h5c 使用說明

下面我們以 Cifar100 為例來展示我們自創的數據集 X.h5c(我將其上傳到了百度雲盤「鏈接:https://pan.baidu.com/s/1nzaicwHmFZH9Xgf2foSw6Q 密碼:bl2e」可以下載直接使用;亦可你自己生成,不過我推薦自己生成,可以對數據集加深理解)

cifar100 = h5c.root.cifar100
cifar100
/cifar100 (Group) ‘https://www.cs.toronto.edu/~kriz/cifar.html‘
  children := [‘coarse_label_names‘ (Array), ‘fine_label_names‘ (Array), ‘testX‘ (Array), ‘test_coarse_labels‘ (Array), ‘test_fine_labels‘ (Array), ‘trainX‘ (Array), ‘train_coarse_labels‘ (Array), ‘train_fine_labels‘ (Array)]

‘coarse_label_names‘ 指的是粗粒度或超類標簽名,‘fine_label_names‘ 則是細粒度標簽名。

可以使用 read() 方法直接獲取信息,也可以使用索引的方式獲取。

coarse_label_names = cifar100.coarse_label_names[:]
# 或者
coarse_label_names = cifar100.coarse_label_names.read()
coarse_label_names.astype(‘str‘)
array([‘aquatic_mammals‘, ‘fish‘, ‘flowers‘, ‘food_containers‘,
       ‘fruit_and_vegetables‘, ‘household_electrical_devices‘,
       ‘household_furniture‘, ‘insects‘, ‘large_carnivores‘,
       ‘large_man-made_outdoor_things‘, ‘large_natural_outdoor_scenes‘,
       ‘large_omnivores_and_herbivores‘, ‘medium_mammals‘,
       ‘non-insect_invertebrates‘, ‘people‘, ‘reptiles‘, ‘small_mammals‘,
       ‘trees‘, ‘vehicles_1‘, ‘vehicles_2‘], dtype=‘<U30‘)
fine_label_names = cifar100.fine_label_names[:].astype(‘str‘)
fine_label_names
array([‘apple‘, ‘aquarium_fish‘, ‘baby‘, ‘bear‘, ‘beaver‘, ‘bed‘, ‘bee‘,
       ‘beetle‘, ‘bicycle‘, ‘bottle‘, ‘bowl‘, ‘boy‘, ‘bridge‘, ‘bus‘,
       ‘butterfly‘, ‘camel‘, ‘can‘, ‘castle‘, ‘caterpillar‘, ‘cattle‘,
       ‘chair‘, ‘chimpanzee‘, ‘clock‘, ‘cloud‘, ‘cockroach‘, ‘couch‘,
       ‘crab‘, ‘crocodile‘, ‘cup‘, ‘dinosaur‘, ‘dolphin‘, ‘elephant‘,
       ‘flatfish‘, ‘forest‘, ‘fox‘, ‘girl‘, ‘hamster‘, ‘house‘,
       ‘kangaroo‘, ‘keyboard‘, ‘lamp‘, ‘lawn_mower‘, ‘leopard‘, ‘lion‘,
       ‘lizard‘, ‘lobster‘, ‘man‘, ‘maple_tree‘, ‘motorcycle‘, ‘mountain‘,
       ‘mouse‘, ‘mushroom‘, ‘oak_tree‘, ‘orange‘, ‘orchid‘, ‘otter‘,
       ‘palm_tree‘, ‘pear‘, ‘pickup_truck‘, ‘pine_tree‘, ‘plain‘, ‘plate‘,
       ‘poppy‘, ‘porcupine‘, ‘possum‘, ‘rabbit‘, ‘raccoon‘, ‘ray‘, ‘road‘,
       ‘rocket‘, ‘rose‘, ‘sea‘, ‘seal‘, ‘shark‘, ‘shrew‘, ‘skunk‘,
       ‘skyscraper‘, ‘snail‘, ‘snake‘, ‘spider‘, ‘squirrel‘, ‘streetcar‘,
       ‘sunflower‘, ‘sweet_pepper‘, ‘table‘, ‘tank‘, ‘telephone‘,
       ‘television‘, ‘tiger‘, ‘tractor‘, ‘train‘, ‘trout‘, ‘tulip‘,
       ‘turtle‘, ‘wardrobe‘, ‘whale‘, ‘willow_tree‘, ‘wolf‘, ‘woman‘,
       ‘worm‘], dtype=‘<U13‘)

‘testX‘‘trainX‘ 分別代表數據的測試數據和訓練數據,而其他的節點所代表的含義也是類似的。

例如,我們可以看看訓練集的數據和標簽:

trainX = cifar100.trainX
train_coarse_labels = cifar100.train_coarse_labels
array([11, 15,  4, ...,  8,  7,  1])

shape(50000, 32, 32, 3),數據的獲取,我們一樣可以采用索引的形式或者使用 read()

train_data = trainX[:]
print(train_data[0].shape)
print(train_data.dtype)
(32, 32, 3)
uint8

當然,我們也可以直接使用 trainX 做運算。

for x in cifar100.trainX:
    y = x * 2
    break

print(y.shape)
(32, 32, 3)
h5c.get_node(h5c.root.cifar100, ‘trainX‘)
/cifar100/trainX (Array(50000, 32, 32, 3)) ‘訓練數據‘
  atom := UInt8Atom(shape=(), dflt=0)
  maindim := 0
  flavor := ‘numpy‘
  byteorder := ‘irrelevant‘
  chunkshape := None

更甚者,我們可以直接定義叠代器來獲取數據:

trainX = cifar100.trainX
train_coarse_labels = cifar100.train_coarse_labels
def data_iter(X, Y, batch_size):
    n = X.nrows
    idx = np.arange(n)
    if X.name.startswith(‘train‘):
        np.random.shuffle(idx)
    for i in range(0, n ,batch_size):
        k = idx[i: min(n, i + batch_size)].tolist()
        yield np.take(X, k, 0), np.take(Y, k, 0)
for x, y in data_iter(trainX, train_coarse_labels, 8):
    print(x.shape, y)
    break
(8, 32, 32, 3) [ 7  7  0 15  4  8  8  3]

Bunch 轉換為 HDF5 文件:高效存儲 Cifar 等數據集