Словарь-как эффективное хранение массивов 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
для количества слов, с которыми мне нужно иметь дело.
вопрос заключается в следующем: есть ли способ сериализации моего набора массивов, который будет:
сохраните сами массивы в сжатом двоичном файле формат сродни
.npy
файлы, созданныеscipy.save
?удовлетворить мое требование, чтобы данные считывались с диска в виде словаря, поддерживая связь между словами и массивами?
4 ответов
Как уже предложил Джошадель, я бы пошел на HDF5, самый простой способ-использовать h5py:
вы можете прикрепить несколько атрибутов к массиву с помощью словаря, такого как sintax:
dset.attrs["Name"] = "My Dataset"
где dset-ваш набор данных, который может быть разрезан точно как массив numpy, но в фоновом режиме он не загружает весь массив в память.
вы пробовали просто с помощью 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:
избегайте использования shelve
, Это ошибка и имеет кросс-платформенные проблемы.
проблема памяти, однако, не имеет ничего общего с shelve
. Массивы Numpy обеспечивают эффективную реализацию протокола рассола, и для cPickle.dumps(protocol=-1)
, по сравнению с binary .npy
(только дополнительные заголовки в рассоле, в основном).
поэтому, если binary / pickle недостаточно, вам придется пойти на сжатие. Взгляните на pytables или h5py (разница между этими двумя).
если указать двоичный протокол, в рассоле is достаточно, вы можете рассмотреть что-то более легкое, чем hdf5: проверьте sqlitedict для замены shelve
. Он не имеет дополнительных зависимостей.