Генерация случайных предложений из пользовательского текста в NLTK Python? - PullRequest
7 голосов
/ 19 июля 2009

У меня проблемы с NLTK под Python, в частности с методом .generate ().

генерировать (self, length = 100)

Печать произвольного текста, созданного с использованием модели языка триграмм.

Параметры:

   * length (int) - The length of text to generate (default=100)

Вот упрощенная версия того, что я пытаюсь сделать.

import nltk

words = 'The quick brown fox jumps over the lazy dog'
tokens = nltk.word_tokenize(words)
text = nltk.Text(tokens)
print text.generate(3)

Это будет всегда генерировать

Building ngram index...
The quick brown
None

В отличие от построения случайной фразы из слов.

Вот мой вывод, когда я делаю

print text.generate()

Building ngram index...
The quick brown fox jumps over the lazy dog fox jumps over the lazy
dog dog The quick brown fox jumps over the lazy dog dog brown fox
jumps over the lazy dog over the lazy dog The quick brown fox jumps
over the lazy dog fox jumps over the lazy dog lazy dog The quick brown
fox jumps over the lazy dog the lazy dog The quick brown fox jumps
over the lazy dog jumps over the lazy dog over the lazy dog brown fox
jumps over the lazy dog quick brown fox jumps over the lazy dog The
None

Снова начинаем с того же текста, но затем меняем его. Я также пытался использовать первую главу из Оруэлла 1984 года. Опять же, всегда начинается с первых 3 токенов (в данном случае один из них пробел), а , затем продолжается случайным образом генерировать текст.

Что я здесь не так делаю?

Ответы [ 5 ]

10 голосов
/ 20 июля 2009

Для генерации произвольного текста вам нужно использовать Марковские цепочки

код для этого: отсюда

import random

class Markov(object):

  def __init__(self, open_file):
    self.cache = {}
    self.open_file = open_file
    self.words = self.file_to_words()
    self.word_size = len(self.words)
    self.database()


  def file_to_words(self):
    self.open_file.seek(0)
    data = self.open_file.read()
    words = data.split()
    return words


  def triples(self):
    """ Generates triples from the given data string. So if our string were
    "What a lovely day", we'd generate (What, a, lovely) and then
    (a, lovely, day).
    """

    if len(self.words) < 3:
      return

    for i in range(len(self.words) - 2):
      yield (self.words[i], self.words[i+1], self.words[i+2])

  def database(self):
    for w1, w2, w3 in self.triples():
      key = (w1, w2)
      if key in self.cache:
    self.cache[key].append(w3)
      else:
    self.cache[key] = [w3]

  def generate_markov_text(self, size=25):
    seed = random.randint(0, self.word_size-3)
    seed_word, next_word = self.words[seed], self.words[seed+1]
    w1, w2 = seed_word, next_word
    gen_words = []
    for i in xrange(size):
      gen_words.append(w1)
      w1, w2 = w2, random.choice(self.cache[(w1, w2)])
    gen_words.append(w2)
    return ' '.join(gen_words)

Объяснение: Генерация псевдослучайного текста с марковскими цепями с использованием Python

7 голосов
/ 26 сентября 2009

Вы должны «тренировать» марковскую модель с несколькими последовательностями, чтобы вы также точно отобрали вероятности начального состояния (называемые «пи» на марковском языке). Если вы используете одну последовательность, то вы всегда начнете в том же состоянии.

В случае с Оруэллом 1984 вы хотели бы сначала использовать токенизацию предложений (NLTK очень хорош в этом), затем слово токенизация (получая список списков токенов, а не только один список токенов) и затем подпитывать каждый предложение отдельно к марковской модели. Это позволит ему правильно смоделировать запуск последовательности, вместо того, чтобы застрять в одном способе запуска каждой последовательности.

1 голос
/ 19 июля 2009

Ваш образец корпуса, скорее всего, будет слишком маленьким. Я не знаю, как именно nltk строит свою модель триграмм, но это обычная практика, что начало и конец предложений обрабатываются как-то. Поскольку в вашем корпусе есть только одно начало предложения, это может быть причиной того, что каждое предложение имеет одинаковое начало.

0 голосов
/ 19 июля 2009

Вы уверены, что использование word_tokenize является правильным подходом?

На этой странице групп Google есть пример:

>>> import nltk
>>> text = nltk.Text(nltk.corpus.brown.words()) # Get text from brown
>>> text.generate() 

Но я никогда не использовал nltk, поэтому я не могу сказать, работает ли он так, как вы хотите.

0 голосов
/ 19 июля 2009

Может быть, вы можете отсортировать массив токенов случайным образом перед генерацией предложения.

...