2009-07-19 42 views
7

Tengo problemas con el NLTK en Python, específicamente con el método .generate().Generando oraciones aleatorias de texto personalizado en Python's NLTK?

generar (self, longitud = 100)

Imprimir texto aleatorio, generado utilizando un modelo de lenguaje trigrama.

Parámetros:

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

Aquí es una versión simplificada de lo que estoy tratando.

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) 

Esto siempre generar

Building ngram index... 
The quick brown 
None 

En oposición a la construcción de una frase al azar de las palabras.

Aquí está mi salida cuando lo haga

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 

vez de empezar con el mismo texto, pero variando la misma. También intenté usar el primer capítulo de Orwell's 1984. De nuevo que siempre comienza con los primeros 3 tokens (uno de los cuales es un espacio en este caso) y luego va a generar aleatoriamente el texto.

¿Qué estoy haciendo mal aquí?

Respuesta

-1

Quizás pueda ordenar la matriz de tokens aleatoriamente antes de generar una oración.

+1

El NLTK usa el contexto de las palabras para determinar su uso. Por ejemplo, tienen el texto completo de 'Moby Dick' en el NLTK por ejemplo. Usar generar con eso generará frases que suenan en Meville. Entonces, a menos que sepa algo que yo no sé, supongo que no quiere recurrir a las palabras porque el contexto inicial es significativo. –

+1

tienes razón. Si barajas las palabras, pierdes la información de la que se tratan los trigramas. – Mastermind

-1

¿Estás seguro de que usar word_tokenize es el enfoque correcto?

This Google groups page tiene el ejemplo:

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

Pero nunca he utilizado NLTK, así que no puedo decir si eso funciona de la manera deseada.

+1

nltk.corpus.brown.words() es solo una colección de palabras que viene con NLTK. Intento sembrar el generador con mis propias palabras. –

+0

¿Has comparado tu propia lista de tokens con el corpus marrón? – Mastermind

1

Su corpus de muestra es muy probable que sea demasiado pequeño. No sé cómo exactamente nltk construye su modelo trigram pero es una práctica común que el principio y el final de las oraciones se manejen de alguna manera. Dado que solo hay un comienzo de oración en su corpus, esta podría ser la razón por la cual cada oración tiene el mismo comienzo.

+0

Bueno, eso fue una muestra para los propósitos de SO. Mi muestra real es más grande. Entonces, ¿necesitas puntuación para compensar oraciones? –

+0

Creo que sí, pero si ya probaste un capítulo entero de Orwell (supongo que con puntuación), creo que estaba equivocado. – Mastermind

9

para generar texto aleatorio, U necesidad de utilizar Markov Chains

código para hacer que: 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) 

Explicación: Generating pseudo random text with Markov chains using Python

7

Usted debe ser el modelo de Markov "formación" con múltiples secuencias , para que también muestres con precisión las probabilidades del estado inicial (llamado "pi" en el discurso de Markov). Si usa una sola secuencia, siempre comenzará en el mismo estado.

En el caso de 1984 de Orwell, primero debería usar tokenización de oraciones (NLTK es muy bueno), luego tokenización de palabras (produciendo una lista de tokens, no solo una lista de tokens) y luego alimentar cada oración por separado al modelo de Markov. Esto le permitirá modelar correctamente los inicios de secuencia, en lugar de estar atascado de una sola manera para comenzar cada secuencia.

Cuestiones relacionadas