我正在使用NLTK在语料库中搜索n-gram但在某些情况下需要很长时间。我注意到计算n-gram在其他包中并不常见(显然Haystack有一些功能)。这是否意味着如果我放弃NLTK,我的语料库中有更快的方法可以找到n-gram?如果是这样,我可以用什么来加快速度?
答案 0 :(得分:23)
既然你没有说明你是否想要单词或字符级别的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]
然后将yield
替换为您想要对每个n-gram执行的实际操作(将其添加到dict
,将其存储在数据库中,等等)以消除生成器开销
最后,如果它真的不够快,请将上面的内容转换为Cython并进行编译。使用defaultdict
代替yield
的示例:
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
答案 1 :(得分:8)
您可以使用zip
和splat(*)运算符here找到pythonic,Elegant和fast ngram生成函数:
def find_ngrams(input_list, n):
return zip(*[input_list[i:] for i in range(n)])
答案 2 :(得分:0)
对于角色等级的n-gram,您可以使用以下功能
def ngrams(text, n):
n-=1
return [text[i-n:i+1] for i,char in enumerate(text)][n:]
答案 3 :(得分:0)
def generate_ngrams(words, ngram=2):
return [words[i:i+ngram] for i in range(len(words)-ngram+1)]
sentence = "I really like python, it's pretty awesome."
words = sentence.split()
words
['I', 'really', 'like', 'python,', "it's", 'pretty', 'awesome.']
res = generate_ngrams(words, ngram=2)
res
[['I', 'really'],
['really', 'like'],
['like', 'python,'],
['python,', "it's"],
["it's", 'pretty'],
['pretty', 'awesome.']]
res = generate_ngrams(words, ngram=3)
res
[['I', 'really', 'like'],
['really', 'like', 'python,'],
['like', 'python,', "it's"],
['python,', "it's", 'pretty'],
["it's", 'pretty', 'awesome.']]
res = generate_ngrams(words, ngram=4)
res
[['I', 'really', 'like', 'python,'],
['really', 'like', 'python,', "it's"],
['like', 'python,', "it's", 'pretty'],
['python,', "it's", 'pretty', 'awesome.']]