Быстрый расчет n-грамм - PullRequest
       52

Быстрый расчет n-грамм

18 голосов
/ 29 сентября 2011

Я использую NLTK для поиска n-граммов в корпусе, но в некоторых случаях это занимает очень много времени.Я заметил, что вычисление n-грамм не является необычной функцией в других пакетах (очевидно, в Haystack есть некоторые функции для этого).Означает ли это, что в моем корпусе есть потенциально более быстрый способ найти n-грамм, если я откажусь от NLTK?Если так, что я могу использовать, чтобы ускорить процесс?

Ответы [ 3 ]

23 голосов
/ 29 сентября 2011

Поскольку вы не указали, хотите ли вы 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
8 голосов
/ 06 мая 2015

Вы можете найти питоническую, элегантную и быструю функцию генерации ngram, используя zip и оператор splat (*) здесь :

def find_ngrams(input_list, n):
  return zip(*[input_list[i:] for i in range(n)])
0 голосов
/ 28 августа 2015

Для n-граммов уровня персонажа вы можете использовать следующую функцию

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