2011-09-29 133 views
16

我正在使用NLTK在語料庫中搜索n-gram,但在某些情況下需要很長時間。我注意到計算n-grams在其他軟件包中並不罕見(顯然Haystack有一些功能)。這是否意味着如果我放棄NLTK,那麼在我的語料庫中找到n-gram可能會更快?如果是這樣,我可以用什麼來加快速度?快速n-gram計算

+0

更多閱讀爲有興趣的人:http://packages.python.org/Whoosh/ngram s.html – Trindaz

+0

相關問題:http://cyberoverflow.com/questions/21883108/fast-optimize-n-gram-implementations-in-python – dmcc

回答

21

既然你沒有說明你是想要字還是字符級的n-gram,我只是假設前者,而不失一般性。

我還假設你從一個由字符串表示的標記列表開始。你可以輕鬆地做的是自己寫n-gram提取。

def ngrams(tokens, MIN_N, MAX_N): 
    n_tokens = len(tokens) 
    for i in xrange(n_tokens): 
     for j in xrange(i+MIN_N, min(n_tokens, i+MAX_N)+1): 
      yield tokens[i:j] 

然後用你想利用每個正克(將其添加到dict,它存儲在數據庫中,無論)擺脫發電機開銷的實際行動代替yield

最後,如果真的不夠快,請將上面的代碼轉換爲Cython並編譯它。用例A的yielddefaultdict代替:

def ngrams(tokens, int MIN_N, int MAX_N): 
    cdef Py_ssize_t i, j, n_tokens 

    count = defaultdict(int) 

    join_spaces = " ".join 

    n_tokens = len(tokens) 
    for i in xrange(n_tokens): 
     for j in xrange(i+MIN_N, min(n_tokens, i+MAX_N)+1): 
      count[join_spaces(tokens[i:j])] += 1 

    return count 
+2

新版本的Cython可以識別Python語句,並在可能的情況下加快速度。此外,你在內部迭代中有一個方法查找。在循環外定義'tokenjoiner ='「.join'並替換內部的」「.join應該可以加快速度。 – rocksportrocker

+0

@rocksportrocker:很好的地方,加了你的建議。 –

+0

,你可以用「count.get(....)+ = 1」來重寫內部行「爲避免方法查找引入另一個變量。 – rocksportrocker

7

您可能會發現一個Python的,優雅的和快速的ngram生成功能使用zip和圖示(*)運算符here

def find_ngrams(input_list, n): 
    return zip(*[input_list[i:] for i in range(n)]) 
0

對於字符級的N-克你可以使用以下功能

def ngrams(text, n): 
    n-=1 
    return [text[i-n:i+1] for i,char in enumerate(text)][n:]