Словарь-как эффективное хранение массивов scipy/numpy

фон

проблема, с которой я работаю, заключается в следующем:

  • в контексте эксперимента, который я разрабатываю для своих исследований, я создаю большое количество больших (длина 4M) массивов, которые несколько разрежены и, следовательно, могут быть сохранены как scipy.sparse.lil_matrix экземпляров, или просто как scipy.array экземпляры (увеличение/потеря пространства здесь не проблема).

  • каждый из этих массивов должен быть сопряжен с строка (а именно слово) для данных, чтобы иметь смысл, поскольку они являются семантическими векторами, представляющими значение этой строки. мне нужно сохранить эту пару.

  • векторы для каждого слова в списке строятся один за другим и сохраняются на диске перед переходом к следующему слову.

  • они должны храниться на диске таким образом, который затем может быть извлечен со словарным синтаксисом. Например, если все слова хранятся в DB-подобный файл, мне нужно иметь возможность открывать этот файл и делать такие вещи, как vector = wordDB[word].

ТЕКУЩИЙ ПОДХОД

что я сейчас делаю:

  • используя shelve чтобы открыть полку с именем wordDB

  • каждый раз, когда вектор (в настоящее время с помощью lil_matrix С scipy.sparse) для слова строится, сохраняя вектор в полке:wordDB[word] = vector

  • когда мне нужно использовать векторы во время оценки я сделаю наоборот: откройте полку, а затем вспомните векторы, выполнив vector = wordDB[word] для каждого слова, как они необходимы, так что не все векторы должны храниться в ОЗУ (что было бы невозможно).

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

это, насколько я могу судить, потому что shelve маринует хранящиеся данные, что не является эффективным способом хранения больших массивов, что делает эту проблему хранения неразрешимой с shelve для количества слов, с которыми мне нужно иметь дело.

вопрос заключается в следующем: есть ли способ сериализации моего набора массивов, который будет:

  1. сохраните сами массивы в сжатом двоичном файле формат сродни .npy файлы, созданные scipy.save?

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

4 ответов


Как уже предложил Джошадель, я бы пошел на HDF5, самый простой способ-использовать h5py:

http://h5py.alfven.org/

вы можете прикрепить несколько атрибутов к массиву с помощью словаря, такого как sintax:

dset.attrs["Name"] = "My Dataset"

где dset-ваш набор данных, который может быть разрезан точно как массив numpy, но в фоновом режиме он не загружает весь массив в память.


Я бы предложил использовать scipy.сохранить и иметь словарь между словом и именем файлов.


вы пробовали просто с помощью cPickle солить словарь напрямую через:

import cPickle
DD = dict()
f = open('testfile.pkl','wb')
cPickle.dump(DD,f,-1)
f.close()

кроме того, я бы просто сохранил векторы в большом многомерном массиве с помощью hdf5 или netcdf, если это необходимо, так как это позволяет открыть большой массив, не принося его все в память сразу, а затем получить срезы по мере необходимости. Затем можно связать слова как дополнительную группу в файле netcdf4 / hdf5 и использовать общие индексы для быстрого связывания соответствующего среза из каждой группы или просто назовите группу словом, а затем данные будут вектором. Вам придется играть с тем, что более эффективно.

http://netcdf4-python.googlecode.com/svn/trunk/docs/netCDF4-module.html

Pytables также может быть полезным слоем хранения поверх HDF5:

http://www.pytables.org


избегайте использования shelve, Это ошибка и имеет кросс-платформенные проблемы.

проблема памяти, однако, не имеет ничего общего с shelve. Массивы Numpy обеспечивают эффективную реализацию протокола рассола, и для cPickle.dumps(protocol=-1), по сравнению с binary .npy (только дополнительные заголовки в рассоле, в основном).

поэтому, если binary / pickle недостаточно, вам придется пойти на сжатие. Взгляните на pytables или h5py (разница между этими двумя).

если указать двоичный протокол, в рассоле is достаточно, вы можете рассмотреть что-то более легкое, чем hdf5: проверьте sqlitedict для замены shelve. Он не имеет дополнительных зависимостей.