Markovfy: Gerando texto automático com cadeias de Markov e Python

Nós já falamos sobre geração automática de textos (NLG, Natural Language Generation) aqui no Clube dos Geeks. E vimos um comparativo entre a autoria de textos automática e manual, com vantagens e desvantagens. Hoje trazemos um exemplo mais prático de aplicação de NLG, gerando textos aleatórios baseados em um Corpus linguístico, usando Cadeias de Markov.

Corpus Linguístico

Um Corpus Linguístico é um conjunto de textos orais ou escritos de uma determinada linguagem. Os corpora (plural de corpus) servem como base para análise de linguagem natural. E servem também como base de treinamento para algoritmos de processamento de linguagem natural.

Geralmente, corpora carregam também informações a respeito de suas palavras. Tais informações vão desde a classe gramatical das palavras (ex. Verbo, Substantivo, Adjetivo, etc.) às relações de dependências que as palavras tem umas com as outras.

No nosso exemplo, usaremos um corpus simples, que conta apenas com texto plano, sem nenhuma anotação. A única exigência é que o texto seja pontuado corretamente, com um ponto (.) no final de cada frase. Usaremos o corpus do livro The Adventures of Sherlock Holmes (As Aventuras de Sherlock Holmes). Esse livro é escrito em inglês, mas você pode usar corpora em português ou em outros idiomas.

Cadeia de Markov

Cadeia de Markov é um processo estocástico, ou seja, um conjunto de variáveis aleatórias usadas, em geral, para estudar a evolução de fenômenos. Com cadeia de Markov é possível prever, com base em probabilidade, qual o próximo evento a acontecer.

No caso da geração de textos, dado uma palavra, a cadeia de Markov ajuda a prever qual a próxima palavra a ser adicionada na frase, de acordo com as frequências de sequências das palavras que constituem o corpus de treinamento.

Por exemplo, suponhamos que o corpus usado para treinamento contém as seguintes sentenças:

O gato comeu o peixe.
O cachorro latiu e mordeu o gato.
O cachorro comeu o bife.

Observando a sequência das palavras e a frequência em que cada uma aparece depois de outra, temos a seguinte tabela:

Depois disso, é preciso calcular os pesos de cada item da cadeia. Por exemplo, depois de “o” temos gato (2 vezes), peixe (1 vez), cachorro (2 vezes) e bife (1 vez). São seis palavras no total e quatro palavras únicas, sendo que o peso da palavra é definido pela frequência da palavra dividido pela quantidade total de palavras na sequência. Portanto, a palavra “gato” tem o peso 2/6, como na tabela abaixo:

Suponhamos que a geração da frase comece pela palavra “o”. Então as próximas palavras são definidas pelos pesos que tem, até que um ponto final (.) seja atingido. Então as seguintes frases podem ser geradas:

o gato comeu o cachorro.
o cachorro comeu o gato.

Ops! As frases não fazem o menor sentido não é mesmo? E essa é uma das desvantagens do uso de Cadeias de Markov para geração de texto. Pois se leva em consideração apenas a frequência das palavras e não o seu significado. Isso pode ser evitado de diversas maneiras, dentre elas:

  • O uso de base de dados maiores e portanto mais abrangentes em relação ao idioma, que aumenta as possibilidades de sequências.
  • Mudando o tamanho do estado das cadeias de Markov. Fazendo o algoritmo observar não só o estado (palavra) atual e os pesos dos possíveis próximos estados.
  • A inserção de uma semântica. Que pode ser uma base de conhecimento na qual seja possível aferir que gatos não comem cachorros, por exemplo.

Markovfy

Markovfy é uma biblioteca python para a geração de Cadeias de Markov. Ela é focada na geração de frases automáticas baseadas em corpus, mas pode ser usada para outros fins.

O primeiro passo é instalar a lib, para isso você precisa ter a linguagem Python e gerenciador de pacotes pip instalados em sua máquina.

$ pip install markovify

Depois, você deve baixar o corpus que usaremos para treinamento. Que é o livro As Aventuras de Sherlock Holmes. Clique aqui. Você deve salvá-lo no mesmo diretório onde você criará o script python com o seguinte conteúdo:

import markovify

with open("sherlock.txt") as f:
    text = f.read()

    text_model = markovify.Text(text)

    for i in range(5):
        print(text_model.make_sentence())

O código é bem simples. Na linha 3, importamos o corpus. Na linha 6, treinamos o modelo. E nas linhas 8 e 9, geramos 5 sentenças automáticas.

Além disso, é possível determinar o tamanho da sentença a ser gerada. Para isso, basta definir a quantidade de caracteres que a frase deve ter. Isso pode ser feito editando a linha 9 do nosso script para:

print(text_model.make_short_sentence(140))

Os exemplos de frases geradas são:

“Perhaps it was but one way for the first wife was the ground, that I had been taken.”
“It is true that you had already been made.”
“We have not yet three when we found ourselves in Bow Street.
It was the thought of the drug, beckoning me to be.”
“Holmes stooped to the Temple, and she fell to the floor, instantly gave rise to the spot upon my approaching it, to be embarrassed by the lake.”
“Mr.McCarthy the elder using very strong reason for leaving America.”

Note que nem todas as sentenças fazem sentido. A primeira, por exemplo, não faz sentido nenhum. Para tentar corrigir isso, a nossa alternativa mais imediata é aumentar o tamanho de estados a serem observados. Para isso, basta mudar a linha 6 para:

text_model = markovify.Text(text, state_size=3)

Vale notar que quanto maior o tamanho do estado, maior é a probabilidade de as frases geradas serem exatamente iguais às que estão no corpus.

Textos em português

É possível usar Markovfy para gerar textos em português, ou qualquer outro idioma. No entanto, você vai precisar de um corpus escrito em português, ou no eventual outro idioma.

Eu fiz o teste usando como corpus um dos artigos do Clube dos Geeks, e como resultado foram geradas frases como:

“É claro que deixar um app relativamente pequeno em um curto espaço de tempo, e o Electron.”

ou

“É o que se torna uma alternativa bastante competitiva para o NWJS e o flutter me ajudou muito nisso, além do app ter ficado bonito e rápido.

Conclusão

Gerar texto natural com Cadeias de Markov é relativamente fácil. Entretanto não é perfeito, pois é baseado apenas nos pesos entres os estados, que no caso são as palavras. No entanto, é uma base, um caminho para quem está começando no campo de geração de texto natural.

Todo o código e os corpus usados neste exemplo estão disponíveis no GitHub. Mas se você tem alguma sugestão, dúvida ou crítica, deixe um comentário.

Jayr Alencar

Doutorando em Ciências da Computação no Centro de Informática da Universidade Federal do Pernambuco (CIn - UFPE); Mestre pela mesma instituição; Formado em Análise e Desenvolvimento de Sistemas; Católico; Fã de O Senhor do Anéis.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *


Deprecated: Creation of dynamic property Daisy_Blog_Google_Local::$files is deprecated in /home2/clube692/public_html/wp-content/themes/daisy-blog/inc/blocks/font-family/inc/class-fonts-google-local.php on line 77

Deprecated: Creation of dynamic property Daisy_Blog_Google_Local::$files is deprecated in /home2/clube692/public_html/wp-content/themes/daisy-blog/inc/blocks/font-family/inc/class-fonts-google-local.php on line 77