В чем разница между двумя способами доступа к группе hdf5 в наборе данных SVHN? - PullRequest
0 голосов
/ 08 апреля 2019

Мне нужно прочитать набор данных SVHN, и я пытался прочитать имя файла первого изображения.

Я изо всех сил пытаюсь понять структуру HDF5 и особенно в понимании иерархии / структуры набора данных SVHN

В чем разница между этими двумя подходами к чтению названия изображения?

Я столкнулся с методом 1 в этом скрипте внутри определения функции getName(): https://github.com/bdiesel/tensorflow-svhn/blob/master/digit_struct.py

Я поигрался с файлом формата hdf5 и нашел способ 2, пробуя разные вещи, которые показали тот же результат.

# Both these methods read the first character of the name of the 1st
# image in svhn dataset
f = h5py.File(path_to_svhn_dataset,'r')

# method 1 
f[f['digitStruct']['name'][0][0]].value

# method 2
f[f['digitStruct']['name'].value[0].item()].value[0][0]

Первым изображением является файл с именем «1.png». Оба вышеупомянутых способа получить первый символ имени файла дадут нам int эквивалент ascii '1' -> 49

1 Ответ

1 голос
/ 12 апреля 2019

Во-первых, есть небольшая разница в результатах двух ваших методов.
Метод 1: возвращает полный массив (с закодированным именем файла)
Способ 2: возвращает только первый элемент (символ) массива

Давайте разберем ваш код, чтобы понять, что у вас есть.
Первая часть имеет дело с h5py объектами данных.

f['digitStruct'] -> возвращает h5py группу объект
f['digitStruct']['name'] -> возвращает h5py набор данных object
f['digitStruct']['name'].name -> возвращает имя (путь) объекта набора данных

Примечание:
Набор данных /digitStruct/name содержит «Ссылки на объекты». Каждая запись массива является указателем на другой объект h5py (в данном случае другой набор данных). Например (пробелы, используемые для разграничения двух ссылок на объекты):
f[ f['digitStruct']['name'][0][0] ] -> возвращает объект, указанный в [0] [0]
Итак, внешний f[ obj_ref ] работает так же, как и другие ссылки на объекты.

В случае f['digitStruct']['name'][0][0] это объект, указывающий на набор данных /#refs#/b Другими словами, f['digitStruct']['name'][0][0] ссылается на тот же объект, что и: f['#refs#']['b'] или f['/#refs#/b']

Так много для ссылок на h5py.
Давайте продолжим получать данные из этой ссылки на объект, используя Метод 1 .

f[f['digitStruct']['name'][0][0]].value -> возвращает весь набор данных /#refs#/b в виде массива NumPy.

Однако dataset.value устарела, и индексирование NumPy является предпочтительным, например: f[f['digitStruct']['name'][0][0]][:] (чтобы получить весь массив)

Примечание: оба возвращают весь массив закодированных символов. На данный момент, получить имя Python и NumPy функциональность. Используйте это, чтобы вернуть имя файла в виде строки:
f[f['digitStruct']['name'][0][0]][:].tostring().decode('ascii')

Теперь давайте разберем ссылку на объект, который вы использовали для Метод 2 .

f['digitStruct']['name'].value -> возвращает весь набор данных /digitStruct/name в виде массива NumPy. Имеет 13 068 строк со ссылками на объекты

f['digitStruct']['name'].value[0] -> первая строка

f['digitStruct']['name'].value[0].item() -> копирует этот элемент массива в скаляр Python

Итак, все они указывают на один и тот же объект:
Метод 1: f['digitStruct']['name'][0][0]
Метод 2: f['digitStruct']['name'].value[0].item()
И оба они такие же, как f['#refs#']['b'] или f['/#refs#/b'] для этого примера.

Как и в методе 1, получение строки - это функциональность Python и NumPy.

f[f['digitStruct']['name'].value[0].item()][:].tostring().decode('ascii')

Да, ссылки на объекты сложны ....
Моя рекомендация:
Извлечение массивов NumPy из объектов с использованием индексации NumPy вместо .value (как показано в Модифицированном способе 1 выше).

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

import h5py

# Both of these methods read the name of the 1st
# image in svhn dataset
f = h5py.File('test_digitStruct.mat','r')
print (f['digitStruct'])
print (f['digitStruct']['name'])
print (f['digitStruct']['name'].name)

# method 1
print('\ntest method 1')
print (f[f['digitStruct']['name'][0][0]])
print (f[f['digitStruct']['name'][0][0]].name)
#  both of these get the entire array / filename:
print (f[f['digitStruct']['name'][0][0]].value)
print (f[f['digitStruct']['name'][0][0]][:]) # same as .value above
print (f[f['digitStruct']['name'][0][0]][:].tostring().decode('ascii'))

# method 2
print('\ntest method 2')
print (f[f['digitStruct']['name'].value[0].item()]) 
print (f[f['digitStruct']['name'].value[0].item()].name) 

# this only gets the first array member / character:
print (f[f['digitStruct']['name'].value[0].item()].value[0][0])
print (f[f['digitStruct']['name'].value[0].item()].value[0][0].tostring().decode('ascii'))
#  this gets the entire array / filename:
print (f[f['digitStruct']['name'].value[0].item()][:])
print (f[f['digitStruct']['name'].value[0].item()][:].tostring().decode('ascii'))

Вывод из двух последних операторов печати для каждого метода идентичен:

[[ 49]
 [ 46]
 [112]
 [110]
 [103]]
1.png
...