2012-05-27 4 views
2

У меня есть небольшая программа, которая использует NLTK для получения частотного распределения довольно большого набора данных. Проблема в том, что после нескольких миллионов слов я начинаю есть всю оперативную память в своей системе. Вот что я считаю соответствующие строки кода:Python NLTK FreqDist() Сокращение использования памяти путем написания k, v на диск?

freq_distribution = nltk.FreqDist(filtered_words)    # get the frequency distribution of all the words 
top_words = freq_distribution.keys()[:10]      # get the top used words 
bottom_words = freq_distribution.keys()[-10:]     # get the least used words 

Там должен быть способ, чтобы написать ключ, значение магазина на диск, я просто не знаю, как. Я стараюсь держаться подальше от хранилища документов, такого как MongoDB, и оставаться чисто pythonic. Если у кого-то есть предложения, я был бы признателен.

ответ

5

По случайному совпадению, у меня была та же проблема в прошлом месяце. Я пытался использовать NLTK и FreqDist для создания n-грамменных таблиц частоты из больших наборов данных (например, английских Википедии и наборов данных Гутенберга). Мой 8-гигабайтный компьютер мог хранить модель униграммы в памяти, но не биграммный.

Моим решением было использовать BerkeleyDB, в котором хранится база данных k, v на диск; но также хранит кеш-память в памяти для скорости. Для частотных распределений это ОЧЕНЬ медленно, поэтому я также создал свои собственные подтаблицы в памяти с помощью FreqDist, а затем периодически сохранял их в BerkeleyDB (обычно каждые 1000 или около того входных файлов). Это значительно уменьшает запись BerkeleyDB, поскольку она удаляет много дубликатов - например. «the» в модели униграмм записывается только один раз, а не много 1000000 раз. Я написал здесь:

http://www.monlp.com/2012/05/17/using-berkeleydb-to-create-a-large-n-gram-table/

Проблема с использованием рассола является то, что вы должны хранить все распределение в памяти. Единственный способ быть чисто pythonic - написать свою собственную реализацию, с ее собственной k, v дисковой базой данных и, возможно, вашим собственным кэшем в памяти. Использование BerkeleyDB намного проще и эффективнее!

+0

Я читаю ваше сообщение прямо сейчас и планирую посмотреть, смогу ли я запустить его для моих нужд в течение следующего часа или около того. Мне очень нравится ваш подход, потому что он позволит задать уровень запроса, если я сломаю анализ вниз по датам документов. Я опубликую, как это происходит/любые изменения, которые я делаю. – secumind

+0

Я немного изменил ваш метод, чтобы соответствовать моим потребностям, но общий подход работал отлично, спасибо! – secumind

2

Я использовал модуль JSON для хранения больших словарей (или других структур данных) в таких ситуациях. Я думаю, что pickle или cpickle может быть более эффективным, если вы не хотите хранить данные в удобочитаемой форме (часто полезно для nlp).

Вот как я это делаю:

import json 
d = {'key': 'val'} 
with open('file.txt', 'w') as f: 
    json.dump(d, f) 

Затем, чтобы получить,

with open('file.txt', 'r') as f: 
    d = json.loads(f.read()) 

 Смежные вопросы

  • Нет связанных вопросов^_^