在Python的NLTK中从自定义文本生成随机句子?

时间:2009-07-19 15:41:58

标签: python random nltk

我在Python下使用NLTK遇到了麻烦,特别是.generate()方法。

  

生成(自我,长度= 100)

     

打印使用trigram语言模型生成的随机文本。

     

参数:

   * 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

再次以相同的文字开头,然后改变它。我也尝试过使用Orwell 1984年的第一章。再次总是从前3个令牌开始(其中一个是本例中的空格),然后然后随机生成文本。

我在这里做错了什么?

5 个答案:

答案 0 :(得分:10)

要生成随机文字,U需要使用Markov Chains

代码:from here

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)

解释: Generating pseudo random text with Markov chains using Python

答案 1 :(得分:7)

你应该“训练”具有多个序列的马尔可夫模型,这样你就可以准确地采样起始状态概率(在Markov-speak中称为“pi”)。如果您使用单个序列,那么您将始终以相同的状态开始。

在Orwell 1984的情况下,你首先要使用句子标记(NLTK非常擅长),然后是单词标记化(产生标记列表,而不仅仅是单个标记列表),然后每个句子分别与马尔可夫模型。这将允许它正确地模拟序列启动,而不是卡在单一的方式来启动每个序列。

答案 2 :(得分:1)

您的样本语料库很可能太小。我不知道nltk究竟是如何构建其三元模型的,但通常的做法是以某种方式处理句子的开头和结尾。由于你的语料库中只有一个句子的开头,这可能就是为什么每个句子都有相同的开头。

答案 3 :(得分:-1)

也许您可以在生成句子之前随机对标记数组进行排序。

答案 4 :(得分:-1)

您确定使用word_tokenize是正确的做法吗?

This Google groups page有例子:

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

但是我从来没有使用过nltk,所以我不能说这是否按你想要的方式工作。