В чем разница между двумя способами доступа к группе hdf5 в наборе данных SVHN?

Мне нужно прочитать набор данных 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

Насколько я понимаю, у вас есть данные изображения SVHN в файле HDF5, но форматы схемы и набора данных в файле мне непонятны. Можете ли вы поделиться подробностями? Тогда, возможно, я смогу помочь. Кроме того, вы всегда можете открыть файл HDF5 с помощью HDFViewer, чтобы «увидеть», что там находится (иерархия групп и наборов данных вместе с данными).

kcw78 09.04.2019 02:28

Я изо всех сил пытаюсь понять схему и не могу ее визуализировать. Я пробовал HDFViewer, но это не сработало. Файл большой, но если это поможет, к нему можно получить доступ здесь: ufldl.stanford.edu/housenumbers Также есть ядро ​​​​kaggle, где есть набор данных: kaggle.com/stanfordu/street-view-house-numbers Я прошу прощения за то, что не могу предоставить больше контента здесь.

patro 09.04.2019 02:42

Вчера я просмотрел эти 2 места и не нашел файлов HDF5 (.h5). В первой ссылке есть файлы tar.gz и .mat. В файлах tar.gz есть файлы png, а в digitStruct.mat — нет HDF5. То же самое на сайте kaggle. Вы создали файл h5 из другой программы?

kcw78 09.04.2019 17:16

@ kcw78 Спасибо за проверку. digitStruct.mat фактически закодирован в формате HDF5. Я использовал h5py для чтения файла digitStruct.mat. «path_to_svhn_dataset» в предоставленном фрагменте кода — это путь к файлу digitStruct.mat. Извиняюсь за путаницу.

patro 10.04.2019 01:46

Пало, я не понимаю, что у тебя есть. Я не думаю, что digitStruct.mat является файлом HDF5. Я попытался открыть его с помощью функции h5py.File('digitStruct.mat','r') и получил большую трассировку. .mat обычно представляет собой файл Matlab (или ярлык для таблицы MS/Access).

kcw78 10.04.2019 22:10

Я не уверен, как помочь здесь. :) Я могу открыть digitStruct.mat с помощью h5py.File, используя ту же команду (у меня абсолютный путь). Моя версия Python 3.6.7. Могу я узнать, какое исключение вы видите? Если это не подходящее место для обсуждения, пожалуйста, дайте мне знать об этом.

patro 11.04.2019 05:56

Пало, я добился прогресса. Я отказался от файлов на standford.edu. Я скачал файлы с kaggle.com и смог открыть test_digitStruct.mat; h5py.File() работает нормально. Теперь, когда я вижу схему и данные, я понимаю, почему возникает так много вопросов о данных SVHN. Это не простая модель данных. Набор данных /digitStruct/name содержит ссылки на объекты, которые указывают на наборы данных в группе /#ref#/, и эти наборы данных имеют ссылки на другие наборы данных. Его сложно разгадать. Я напишу полный ответ, который покажет, как они работают, и опубликую позже.

kcw78 12.04.2019 00:34
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
7
914
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

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

f['digitStruct'] -> возвращает объект h5py группа
f['digitStruct']['name'] -> возвращает объект h5py набор данных
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

Обратите внимание, ссылки для получения объекта в наборе данных f['digitStruct']['name'] используют индексацию NumPy. Я скопировал формат индекса [0][0], использованный в исходном посте. Вы также можете использовать [0,0] (что может быть более интуитивно понятным). Кроме того, поскольку это стандартное индексирование NumPy, первый индекс указывает на строку в наборе данных. Вы можете использовать [-1,0] (или [-1][0]), чтобы получить последнюю строку.

kcw78 12.04.2019 19:51

Другие вопросы по теме