2012-05-27 2 views
2

약간 큰 데이터 세트의 빈도 분포를 얻기 위해 NLTK를 사용하는 작은 프로그램이 있습니다. 문제는 수백만 단어가 지나면 시스템의 모든 RAM을 먹기 시작한다는 것입니다. 여기에 코드의 관련 라인을 생각하는 내용은 다음과 같습니다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와 같은 문서 저장소에서 멀리 떨어져 있고 순수하게 파이썬 적으로 머물러 있습니다. 누구든지 몇 가지 제안 사항이 있으면 감사하게 생각합니다.

답변

5

, 내가 지난 달에 같은 문제가 있었다. 나는 NLTK와 FreqDist를 사용하여 큰 데이터 세트 (예 : 영문 위키피디아와 구텐베르크 데이터 세트)에서 n-gram 빈도 테이블을 만들려고했다. 내 8GB 머신은 유니그램 모델을 메모리에 저장할 수 있지만 bigram은 저장할 수 없습니다.

내 솔루션은 k, v 데이터베이스를 디스크에 저장하는 BerkeleyDB를 사용하는 것이 었습니다. 또한 속도를 위해 메모리 내장 테이블 캐시를 저장합니다. 빈도 분포의 경우 매우 느리기 때문에 FreqDist를 사용하여 메모리에 자체 하위 테이블을 만든 다음 정기적으로 BerkeleyDB에 저장합니다 (대개 1000 개 정도의 입력 파일). 이렇게하면 많은 중복을 제거하기 때문에 BerkeleyDB 기록을 크게 줄일 수 있습니다. Unigram 모델의 "the"는 오직 100,0000 번이 아닌 한 번만 쓰여집니다. 난 여기가 쓴 :

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

피클을 사용하는 데 문제가 메모리에 전체 분포를 저장해야한다는 것입니다. 순전히 비단뱀이되는 유일한 방법은 자신의 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())