Python — Поиск уникальных столбцов в наборе данных HDF5

я использую HDF5 хранить очень большие наборы данных uint8s (400 х 121000000). В столбцах огромное количество избыточности (97% столбцов не являются уникальными). Мне нужно эффективно объединять дублирующиеся столбцы. Это означает, что мне нужно удалить повторяющиеся столбцы, сохраняя при этом метаданные, чтобы запомнить, какие столбцы были объединены.

Я в настоящее время использую Python с h5py, но если у кого-то есть эффективное решение C ++, я мог бы просто использовать boost::python реализовать это.

Мое текущее решение состоит в загрузке блоков набора данных в NumPy массив и используя dictionary хранить уникальные столбцы и метаданные.

Обратите внимание HashableNDArray класс можно найти Вот. Я просто переименовал его.

def find_column_redundancy(dataset):
n_columns = dataset.shape[1]
block_size = 500000
n_blocks = int(ceil(float(n_columns) / float(block_size)))

d = {}
analysed_column_count = 0
for block in xrange(n_blocks):
block_offset = block*block_size
block_data = dataset[:, block_offset : block_offset+block_size]
for i in xrange(block_data.shape[1]):
hashable_array = HashableNDArray(np.ascontiguousarray(block_data[:, i]))
d[hashable_array] = np.append(d.get(hashable_array, np.array([], dtype=np.int32)), block_offset + i)
analysed_column_count += 1

return d

Как только я перебрал все столбцы, я возвращаю dictionary что я использую, чтобы написать новый HDF5 набор данных с удаленной избыточностью.

Мне нужна помощь; это не может быть оптимальным!

Спасибо!

1

Решение

Я сделал некоторые профилирование с kernprof и оптимизировал мой код.

  • Самым большим узким местом было создание объектов HashableNDArray. Я обнаружил, что, делая эти массивы только для чтения, я мог хэшировать их буфер данных, не используя класс-оболочку. Кроме того, извлечение данных буфера в виде строки позволяет значительно ускорить хеширование. Чтобы восстановить данные столбца, я использую np.frombuffer(dict_key, dtype=np.uint8),

  • Я также получил небольшое ускорение, заменив словарь defaultdict и устранение блока try / кроме.

  • Поскольку мои данные содержат только двоичные значения, я обнаружил, что с помощью np.packbits на столбцах позволяет экономить память в 8 раз при хранении ключей и позволяет сопоставлять идентичные столбцы. Единственное, что вам нужно помнить, чтобы использовать np.unpackbits это фактическая длина ваших столбцов, поскольку пустые байты заполнены неполными байтами с конечным 0.

Наконец, я точно настроил block_size, чтобы использовать максимальный объем доступной памяти. Это позволяет немного увеличить время чтения с диска и значительно повысить загрузку процессора.

Эта функция использовалась для моих данных за ~ 18 часов, а теперь она работает за ~ 0.5 часа!

def find_column_redundancy(dataset):
n_columns = dataset.shape[1]
block_size = 10000000
n_blocks = int(ceil(float(n_columns) / float(block_size)))

d = defaultdict(list)
analysed_column_count = 0
for block in xrange(n_blocks):
block_offset = block*block_size
block_data = dataset[:, block_offset : block_offset+block_size]
block_data = np.asfortranarray(block_data)
block_data = np.packbits(block_data, axis=0)
block_data.flags.writeable = False
for i in xrange(block_data.shape[1]):
d[block_data[:, i].data[:]].append(block_offset + i)
analysed_column_count += 1

print float(analysed_column_count)/n_columns*100, "% completed. Dictionnary has", len(d), "items."
return d
3

Другие решения


По вопросам рекламы [email protected]