Могу ли я преобразовать путь к каталогу во что-то, что можно передать в таблицу данных Python hdf5? - PullRequest
0 голосов
/ 11 ноября 2019

Мне было интересно, как преобразовать строку или путь во что-то, что может быть передано в таблицу hdf5. Например, я возвращаю массив numy img, метку и путь к изображению из загрузчика данных Pytorch, где путь к изображению будет выглядеть следующим образом:

('mults/train/0/5678.ndpi/40x/40x-236247-16634-80384-8704.png',)

Я в основном хочу передать егов таблицу hdf5 вот так:

hdf5_file = h5py.File(path, mode='w')
hdf5_file.create_dataset(str(phase) + '_img_paths', (len(dataloaders_dict[phase]),))

Я не совсем уверен, возможно ли то, что я хочу сделать. Может быть, я неправильно вводить такие данные в таблицу.

Я пытался:

hdf5_file.create_dataset(str(phase) + '_img_paths', (len(dataloaders_dict[phase]),),dtype="S10")

Но получаю эту ошибку:

 hdf5_file[str(phase) + '_img_paths'][i] = str(paths40x)
  File "h5py/_objects.pyx", line 54, in h5py._objects.with_phil.wrapper
  File "h5py/_objects.pyx", line 55, in h5py._objects.with_phil.wrapper
  File "/anaconda3/lib/python3.6/site-packages/h5py/_hl/dataset.py", line 708, in __setitem__
    self.id.write(mspace, fspace, val, mtype, dxpl=self._dxpl)
  File "h5py/_objects.pyx", line 54, in h5py._objects.with_phil.wrapper
  File "h5py/_objects.pyx", line 55, in h5py._objects.with_phil.wrapper
  File "h5py/h5d.pyx", line 211, in h5py.h5d.DatasetID.write
  File "h5py/h5t.pyx", line 1652, in h5py.h5t.py_create
  File "h5py/h5t.pyx", line 1713, in h5py.h5t.py_create
TypeError: No conversion path for dtype: dtype('<U64')

1 Ответ

0 голосов
/ 15 ноября 2019

У вас есть несколько вариантов сохранения строковых данных:

  1. Вы можете создать стандартный набор данных в h5py или PyTables и определить со сколь угодно большим размером строки. Это самый простой метод, но есть риск, что ваша произвольно большая строка не достаточно велика. :)
  2. Кроме того, можно создать набор данных переменной длины. PyTables вызывает этот тип набора данных как VLArray, а объект, который он использует, это класс VLStringAtom (). h5py использует стандартный набор данных, но dtype ссылается на special_dtype (vlen = str) (обратите внимание, что если вы используете h5py 2.10, вы можете использовать вместо него string_dtype ()).

Я создал пример, который показывает, каксделать это как для PyTables, так и для h5py. Он построен на основе процедур, упомянутых в ваших комментариях. Я не копировал весь код - только то, что было необходимо, чтобы получить имена файлов и перемешать их. Кроме того, обнаруженный мной набор данных kaggle имеет другую структуру каталогов, поэтому я изменил переменную cat_dog_train_path для соответствия.

from random import shuffle
import glob
shuffle_data = True  # shuffle the addresses before saving
cat_dog_train_path = '.\PetImages\*\*.jpg'

# read addresses and labels from the 'train' folder
addrs = glob.glob(cat_dog_train_path, recursive=True)
print (len(addrs))
labels = [0 if 'cat' in addr else 1 for addr in addrs]  # 0 = Cat, 1 = Dog

# to shuffle data
if shuffle_data:
    c = list(zip(addrs, labels))
    shuffle(c)
    addrs, labels = zip(*c)

# Divide the data into 10% train only, no validation or test
train_addrs = addrs[0:int(0.1*len(addrs))]
train_labels = labels[0:int(0.1*len(labels))]

print ('Check glob list data:')
print (train_addrs[0])
print (train_addrs[-1])

import tables as tb

# Create a hdf5 file with PyTaables and create VLArrays
# filename to save the hdf5 file
hdf5_path = 'PetImages_data_1.h5'  
with tb.File(hdf5_path, mode='w') as h5f:
    train_files_ds = h5f.create_vlarray('/', 'train_files', 
                                        atom=tb.VLStringAtom() )
    # loop over train addresses
    for i in range(len(train_addrs)):
        # print how many images are saved every 1000 images
        if i % 500 == 0 and i > 1:
            print ('Train data: {}/{}'.format(i, len(train_addrs)) )
        addr = train_addrs[i]
        train_files_ds.append(train_addrs[i].encode('utf-8'))

with tb.File(hdf5_path, mode='r') as h5f:
    train_files_ds = h5f.root.train_files
    print ('Check PyTables data:')
    print (train_files_ds[0].decode('utf-8'))
    print (train_files_ds[-1].decode('utf-8'))

import h5py

# Create a hdf5 file with h5py and create VLArrays
# filename to save the hdf5 file
hdf5_path = 'PetImages_data_2.h5'  
with h5py.File(hdf5_path, mode='w') as h5f:
    dt = h5py.special_dtype(vlen=str) # can use string_dtype() wiuth h5py 2.10
    train_files_ds = h5f.create_dataset('/train_files', (len(train_addrs),), 
                                        dtype=dt )

    # loop over train addresses
    for i in range(len(train_addrs)):
        # print how many images are saved every 1000 images
        if i % 500 == 0 and i > 1:
            print ('Train data: {}/{}'.format(i, len(train_addrs)) )
        addr = train_addrs[i]
        train_files_ds[i]= train_addrs[i]

with h5py.File(hdf5_path, mode='r') as h5f:
    train_files_ds = h5f['train_files']
    print ('Check h5py data:')
    print (train_files_ds[0])
    print (train_files_ds[-1])
...