Мои данные хранятся в формате .h5. Я использую генератор данных, чтобы соответствовать модели, и он очень медленный. Фрагмент моего кода приведен ниже.
def open_data_file(filename, readwrite="r"):
return tables.open_file(filename, readwrite)
data_file_opened = open_data_file(os.path.abspath("../data/data.h5"))
train_generator, validation_generator, n_train_steps, n_validation_steps = get_training_and_validation_generators(
data_file_opened,
......)
где:
def get_training_and_validation_generators(data_file, batch_size, ...):
training_generator = data_generator(data_file, training_list,....)
функция генератора данных выглядит следующим образом:
def data_generator(data_file, index_list,....):
orig_index_list = index_list
while True:
x_list = list()
y_list = list()
if patch_shape:
index_list = create_patch_index_list(orig_index_list, data_file, patch_shape,
patch_overlap, patch_start_offset,pred_specific=pred_specific)
else:
index_list = copy.copy(orig_index_list)
while len(index_list) > 0:
index = index_list.pop()
add_data(x_list, y_list, data_file, index, augment=augment, augment_flip=augment_flip,
augment_distortion_factor=augment_distortion_factor, patch_shape=patch_shape,
skip_blank=skip_blank, permute=permute)
if len(x_list) == batch_size or (len(index_list) == 0 and len(x_list) > 0):
yield convert_data(x_list, y_list, n_labels=n_labels, labels=labels, num_model=num_model,overlap_label=overlap_label)
x_list = list()
y_list = list()
add_data() выглядит следующим образом:
def add_data(x_list, y_list, data_file, index, augment=False, augment_flip=False, augment_distortion_factor=0.25,
patch_shape=False, skip_blank=True, permute=False):
'''
add qualified x,y to the generator list
'''
# pdb.set_trace()
data, truth = get_data_from_file(data_file, index, patch_shape=patch_shape)
if np.sum(truth) == 0:
return
if augment:
affine = np.load('affine.npy')
data, truth = augment_data(data, truth, affine, flip=augment_flip, scale_deviation=augment_distortion_factor)
if permute:
if data.shape[-3] != data.shape[-2] or data.shape[-2] != data.shape[-1]:
raise ValueError("To utilize permutations, data array must be in 3D cube shape with all dimensions having "
"the same length.")
data, truth = random_permutation_x_y(data, truth[np.newaxis])
else:
truth = truth[np.newaxis]
if not skip_blank or np.any(truth != 0):
x_list.append(data)
y_list.append(truth)
Обучение модели:
def train_model(model, model_file,....):
model.fit(training_generator,
steps_per_epoch=steps_per_epoch,
epochs=n_epochs,
verbose = 2,
validation_data=validation_generator,
validation_steps=validation_steps)
Мой набор данных большой: data.h5 — 55 ГБ. Для завершения одной эпохи требуется около 7000 с. И я получаю ошибку ошибки сегментации примерно через 6 эпох. Размер пакета установлен равным 1, потому что в противном случае я получаю сообщение об исчерпании ресурсов. Есть ли эффективный способ чтения data.h5 в генераторе, чтобы обучение проходило быстрее и не приводило к ошибкам нехватки памяти?
Насколько велик файл .h5?
Похоже, вы используете pytables, а не h5py.
Размер набора данных составляет 55 ГБ. Данные хранятся в формате .h5 как data.h5. Я использую pytables, чтобы открыть файл.
Сколько раз вы читаете данные из файла .h5 за 1 эпоху? (сколько вызовов для чтения функций?) Скорость уменьшается с увеличением количества операций ввода/вывода. Кроме того, вы используете причудливую индексацию? Это медленнее, чем простые срезы.
@ kcw78 Количество шагов обучения в каждой эпохе — 2268. Размер моего пакета — 1. Если я увеличу размер пакета, я получу ошибку исчерпания ресурсов. Даже при размере пакета 1 я получаю ошибку сегментации примерно через 6 эпох. Я не использую какую-либо причудливую индексацию. Моя функция генератора данных представлена выше.
За исключением функции
open_data_file()
, я не вижу никакого кодаtables
в вашем сообщении. (Это в функцииadd_data()
?) Узкие места в производительности трудно выявить и устранить, не видя код и не понимая схему файла .h5. Если вы не хотите делиться этой информацией, вам нужно написать код, имитирующий то, какadd_data()
читает ваш файл .h5. Затем вы можете протестировать производительность чтения файлов, чтобы определить, не является ли это причиной проблем с производительностью и стабильностью.Я отредактировал вопрос с помощью функции
add_data()
. Я использовал таблицы при создании данных как data.h5.Хорошо, я думаю, я понял.
data_generator()
зацикливается наwhile len(index_list) > 0:
, вызываяadd_data()
, который вызываетget_data_from_file()
. Я предполагаю, что эта функция вызывает функцииtables
для чтения ваших данных .h5. Насколько великindex_list
? Это количество раз, когда вы обращаетесь к файлу в каждую эпоху. Умножьтеlen(index_list)
X эпох (2268), чтобы получить общее количество эпох. Это может быть очень большое число, которое объясняет, почему ваш процесс такой медленный. Чтобы повысить производительность, вам необходимо сократить количество вызовов чтения, считывая больше данных за один раз.Длина списка индексов — 3325. Количество шагов обучения в каждой эпохе — 2268. Скажите, пожалуйста, что нужно изменить, чтобы читать больше данных за один раз? Если я увеличу размер пакета, я получу ошибку исчерпания ресурсов.
Цель состоит в том, чтобы уменьшить количество вызовов функции
tables
для чтения данных. Трудно дать конкретный совет без источника дляget_data_from_file()
. Что ты читаешь? Данные изображения? Вы читаете по 1 картинке за раз? Если это так, вам нужно реорганизовать свой код, чтобы считывать все нужные изображения для 1 эпохи за 1 вызов. Есть аналогичные вопросы на SO. Дополнительные идеи читайте в комментариях: coderhelper.com/a/67655331/10462884 и coderhelper.com/a/66681133/10462884.Спасибо за ссылки. Я читаю данные изображения. Это репозиторий, который я использую для создания данных: github.com/woodywff/brats_2019/blob/…
Как отмечалось выше, основная проблема, вероятно, связана с неэффективными моделями доступа к данным. HDF5 поддерживает сжатие. Ваш файл данных сильно сжат? Это может быть одним из потенциально многих факторов, которые могут способствовать замедлению ввода-вывода. Кроме того, на аппаратном уровне: spinny или SSD? Объем оперативной памяти? Если у вас большой объем ОЗУ (например, 256 ГБ), а размер несжатых изображений составляет примерно 60 ГБ, рассмотрите возможность загрузки всего ввода в память для быстрого доступа. Если это все еще медленно, то структуры данных/алгоритмы неэффективны или изображения слишком велики для того, для чего был написан код - возможно, даунсэмплинг.
@Salmonstrikes Да, мои данные сильно сжаты (уровень сжатия равен 5 по шкале от 0 до 9). Должен ли я уменьшить или увеличить уровень сжатия? В моей оперативной памяти 32 ГБ памяти, в моем графическом процессоре — 10 ГБ, а мои данные — 55 ГБ (хранятся как data.h5). Данные создаются как:
data_storage = hdf5_file.create_earray(hdf5_file.root, 'data', tables.Float32Atom(), shape=data_shape, filters=filters, expectedrows=n_samples)
@Salmonstrikes делает хорошее замечание о сжатии - оно замедляет ввод-вывод. Иногда это может быть существенно (особенно при более высоких уровнях сжатия — я использую только level=1). Достаточно просто распаковать файл и сравнить производительность. В PyTables есть утилита
ptrepack
, которая может это сделать. Вот как распаковать файл данных в новый файл:ptrepack --complevel 0 data.h5 data_unc.h5
. Измените имя файла данных в коде наdata_unc.h5
.