Използвам NLTK за търсене на n-грами в корпус, но в някои случаи отнема много време. Забелязах, че изчисляването на n-грамове не е необичайна функция в други пакети (очевидно Haystack има някаква функционалност за това). Това означава ли, че има потенциално по-бърз начин за намиране на n-грами в моя корпус, ако изоставя NLTK? Ако е така, какво мога да използвам, за да ускоря нещата?
Бързо изчисляване на n-грам
Отговори (3)
Тъй като не посочихте дали искате n-грами на ниво дума или знак, просто ще приема първото, без загуба на общост.
Предполагам също, че започвате със списък от токени, представени от низове. Това, което можете лесно да направите, е сами да напишете извличане на n-грам.
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-грам (добавете го към 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
Може да намерите питонична, елегантна и бърза функция за генериране на ngram, използваща zip
и splat (*) оператор тук:
def find_ngrams(input_list, n):
return zip(*[input_list[i:] for i in range(n)])
За n-грами на ниво символ можете да използвате следната функция
def ngrams(text, n):
n-=1
return [text[i-n:i+1] for i,char in enumerate(text)][n:]