Мне нужно прочитать набор данных 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
Я изо всех сил пытаюсь понять схему и не могу ее визуализировать. Я пробовал HDFViewer, но это не сработало. Файл большой, но если это поможет, к нему можно получить доступ здесь: ufldl.stanford.edu/housenumbers Также есть ядро kaggle, где есть набор данных: kaggle.com/stanfordu/street-view-house-numbers Я прошу прощения за то, что не могу предоставить больше контента здесь.
Вчера я просмотрел эти 2 места и не нашел файлов HDF5 (.h5). В первой ссылке есть файлы tar.gz и .mat. В файлах tar.gz есть файлы png, а в digitStruct.mat — нет HDF5. То же самое на сайте kaggle. Вы создали файл h5 из другой программы?
@ kcw78 Спасибо за проверку. digitStruct.mat фактически закодирован в формате HDF5. Я использовал h5py для чтения файла digitStruct.mat. «path_to_svhn_dataset» в предоставленном фрагменте кода — это путь к файлу digitStruct.mat. Извиняюсь за путаницу.
Пало, я не понимаю, что у тебя есть. Я не думаю, что digitStruct.mat
является файлом HDF5. Я попытался открыть его с помощью функции h5py.File('digitStruct.mat','r')
и получил большую трассировку. .mat
обычно представляет собой файл Matlab (или ярлык для таблицы MS/Access).
Я не уверен, как помочь здесь. :) Я могу открыть digitStruct.mat с помощью h5py.File, используя ту же команду (у меня абсолютный путь). Моя версия Python 3.6.7. Могу я узнать, какое исключение вы видите? Если это не подходящее место для обсуждения, пожалуйста, дайте мне знать об этом.
Пало, я добился прогресса. Я отказался от файлов на standford.edu. Я скачал файлы с kaggle.com и смог открыть test_digitStruct.mat
; h5py.File()
работает нормально. Теперь, когда я вижу схему и данные, я понимаю, почему возникает так много вопросов о данных SVHN. Это не простая модель данных. Набор данных /digitStruct/name
содержит ссылки на объекты, которые указывают на наборы данных в группе /#ref#/
, и эти наборы данных имеют ссылки на другие наборы данных. Его сложно разгадать. Я напишу полный ответ, который покажет, как они работают, и опубликую позже.
Во-первых, есть небольшая разница в выводе ваших двух методов.
Способ 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]
), чтобы получить последнюю строку.
Насколько я понимаю, у вас есть данные изображения SVHN в файле HDF5, но форматы схемы и набора данных в файле мне непонятны. Можете ли вы поделиться подробностями? Тогда, возможно, я смогу помочь. Кроме того, вы всегда можете открыть файл HDF5 с помощью HDFViewer, чтобы «увидеть», что там находится (иерархия групп и наборов данных вместе с данными).