Словарное эффективное хранение массивов scipy / numpy - PullRequest
7 голосов
/ 16 марта 2011

ПРЕДПОСЫЛКА

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

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

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

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

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

CURRENT APPROACH

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

  • Использование shelve для открытия полки с именем wordDB

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

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

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

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

ПРОБЛЕМА

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

  1. Сохранять сами массивы в сжатом двоичном формате, аналогично.npy файлов, сгенерированных с помощью scipy.save?

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

Ответы [ 4 ]

5 голосов
/ 16 марта 2011

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

http://h5py.alfven.org/

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

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

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

2 голосов
/ 20 июля 2011

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

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

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

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

2 голосов
/ 16 марта 2011

Вы пытались просто использовать 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

2 голосов
/ 16 марта 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...