Como Machine Learning consegue diferenciar heterônimos de Fernando Pessoa

O Projeto de Processamento de Linguagem Natural do Grupo Turing

Lucas Sepeda
Turing Talks
7 min readApr 19, 2020

--

Projeto desenvolvido por: Fernando Matsumoto, Iago Nunes, Igor Câmara, Julia Pocciotti e Lucas Sepeda.

Representação artística dos vários heterônimos de Fernando Pessoa

Introdução

Bem vindos a mais uma edição do Turing Talks! Hoje falaremos sobre um projeto desenvolvido pela área de Processamento de Linguagem Natural do Grupo Turing: um Classificador de Poemas do Fernando Pessoa.

Todo o código para esse projeto (scrappers e modelos) está disponível no GitHub do Grupo Turing.

A maioria pensa com a sensibilidade, e eu sinto com o pensamento. Para o homem vulgar, sentir é viver e pensar é saber viver. Para mim, pensar é viver e sentir não é mais que o alimento de pensar. — Bernardo Soares

O que é Processamento de Linguagem Natural?

Processamento de Linguagem Natural (PLN), ou, em inglês, Natural Language Processing é uma área da inteligência artificial cujo objetivo é a interpretação e manipulação de linguagens humanas. O estudo de PLN envolve várias habilidades distintas. Alguns conhecimentos básicos de linguística são úteis, sobretudo para as tarefas ligadas a pré-processamento. Além disso, há técnicas clássicas, estatísticas e, por fim, de aprendizado de máquina.

Há várias tarefas que são envolvidas por PLN, como análise de sentimentos e tradução automática, por exemplo. Nesse post, veremos mais um pouco sobre uma dessas tarefas, a Classificação de Texto.

De onde surgiu a ideia?

O projeto nasceu como aplicação de assuntos que estávamos estudando dentro do Grupo; os tópicos em questão eram dois: similaridade semântica e lexical e classificação de textos. Ou seja, juntamos ferramentas de PLN e modelos de classificação para comparar e mensurar o sentido de palavras, tanto isoladamente, quanto em um contexto mais amplo de documentos para então realizar uma tarefa clássica de Aprendizado de Máquina, na qual o modelo deve dividir as entradas em diversas categorias.

A ideia surgiu a partir de um artigo discutindo a autoria do Federalist Papers — um conjunto de ensaios publicado por Alexander Hamilton, James Madison e John Jay, sob o pseudônimo Publius. Historiadores discutem a autoria de cada um dos 85 ensaios a partir de características textuais e outras informações pertinentes. No artigo, são utilizadas ferramentas de pré-processamento e clusterização para o problema de atribuição de autoria.

Por que Fernando Pessoa?

Fernando Pessoa (1888–1935)

A resposta para essa pergunta é bem simples. O poeta português Fernando Pessoa se notabilizou, entre outras coisas, por criar o fenômeno da heteronímia. Diferentemente de pseudônimos, os heterônimos criados por Fernando Pessoa possuíam uma personalidade completa e eram muito diferentes em suas próprias filosofias, e, mais especificamente, em seus estilos de escrita.

Fazendo essa simples comparação, é possível notar que, apesar de escritos pelo mesmo autor, os heterônimos Alberto Caeiro e Ricardo Reis diferem muito em sua escrita. Sendo assim, a pergunta que motivou nosso experimento foi: será que, do ponto de vista de um classificador, os heterônimos são mesmo distintos, ou será que possuem características da mesma pessoa por trás deles?

O processo

Obtenção dos textos (corpus)

O primeiro passo para todo projeto de aprendizado de máquina é a obtenção dos dados. Nessa etapa, utilizamos os milhares de textos do Fernando Pessoa disponíveis no Arquivo Pessoa. Usando o framework Scrapy, extraímos os textos do site e formamos um dataset de textos, o qual está disponível no repositório do projeto.

Para cada texto, estão disponíveis também informações como o autor, o título e a data de publicação.

Cinco primeiras linhas do corpus

No processo de extração dos dados, o primeiro passo é localizar as páginas nas quais estão localizados os textos. Em seguida, passamos por cada uma dessas páginas e extraímos as informações de interesse. Por exemplo, o autor do texto encontra-se em uma tag de classe “autor”. Como o texto é recebido em um arquivo html, é necessário convertê-lo para texto simples. Isso foi feito com ajuda de expressões regulares e da biblioteca html2text. Por último, o Scrapy salva automaticamente essas informações em um arquivo csv.

Carregando os dados

Para trabalharmos com os dados, utilizamos pandas para carregar os dados do csv no python. Além disso, retiramos os autores com menos de 80 textos do DataFrame. Fizemos isso para que o modelo fosse mais robusto e evitar sobreajuste.

Carregando os dados do csv usando pandas

Também percebemos que existiam no DataFrame textos em inglês. Contornamos esse problema utilizando a função detect da biblioteca langdetect. É importante mencionar que o algoritmo de detecção de linguagem é não determinístico, ou seja, em alguns textos o resultado pode variar. Portanto, optamos por remover esses textos.

Eliminando textos em inglês

Pré-processamento

Com os textos em mão, ainda era preciso processá-los para que ficassem utilizáveis por modelos de classificação. Esse processo começou pela retirada das stopwords utilizando nltk — palavras que, por serem muito comuns, acabam introduzindo ruído no modelo. Depois, lematizamos e stemizamos o que sobrou usando a biblioteca scpaCy. A lematização (ou lemmatization, em inglês) é o processo de extração da raiz das palavras para sua forma dicionarizada. Já stemização (ou stemming, em inglês) é um processo similar, na qual o radical da palavra é extraído. Assim duas conjugações diferentes de um mesmo verbo passam a ser a mesma palavra. Também deixamos todas as letras minúsculas, para fim de normalização.

Função para lemmatizar o texto

Outro ponto necessário é codificar a coluna que identifica a qual heterônimo pertence um dado poema para ser possível utilizar um algoritmo de classificação. Para essa tarefa, atribuímos números inteiros de 0 a 3 para cada um dos heterônimos que iremos classificar neste modelo utilizando a função LabelEncoder do scikit-learn.

Codificação do nome dos heterônimos

Daí, dividimos o DataFrame em teste e treino e concluímos a etapa de pré-processamento.

Extração de features

Em seguida, é necessário codificar os textos lematizados para um formato que os modelos de classificação consigam lidar. Para isso, utilizamos uma matriz termo-documento com valores ponderados por tf-idf (term frequency-inverse document frequency, ou frequência do termo-inverso da frequência nos documentos) para todos os heterônimos.

O que é a matriz termo-documento?

A matriz termo-documento é composta pelo vocabulário de todos os poemas nas linhas e pelos poemas nas colunas, e os valores são o número de vezes que um determinado termo ocorre naquele poema (term frequency) dividido pelo número de poemas em que o termo aparece (inverse document frequency). Essa divisão é feita pois termos que aparecem em muitos documentos diferentes são pouco significativas para classificar um texto. Por exemplo, se a palavra “casa” aparecesse em todos os poemas de Fernando Pessoa, ela ajudaria pouco na tarefa de atribuir um poema para um heterônimo do poeta. Agora se a palavra “janela”, por exemplo, ocorre apenas nos poemas de um heterônimo, ela nos ajudará muito na classificação.

Criando a matriz

Para criação da matriz utilizamos o implementação já pronta de tf-idf disponível no scikit-learn. Perceba que treinamos o vetor apenas uma vez em todo o vocabulário disponível e então aplicamos a transformação nos DataFrames de treino e teste.

Criação do vetor tf-idf

Com a features extraídas e o pré-processamento realizado, podemos, finalmente, partir para a construção do modelo.

O modelo

Agora que temos o DataFrame pronto para receber modelos, precisamos decidir quais iremos aplicar. Nesse post iremos adotar dois modelos clássicos de PLN: Support Vector Machine e Naive Bayes.

O Support Vector Machine busca, em pouquíssimas palavras encontrar o hiperplano que divide duas classes.

Á esquerda: “Para um espaço de duas dimensões, o hiperplano é uma linha”. Á direita: “Para um espaço de 3 dimensões, o hiperplano é um plano”.

Já o NaiveBayes se baseia em métodos probabilísticos utilizando o famoso teorema de Bayes, nos quais os parâmetros são os documentos e o vetor do tf-idf.

Teorema de Bayes. Muito utilizado nos modelos de PLN.

Mais uma vez, se quiser se aprofundar nos detalhes desses modelos, basta conferir nossos Turing Talks sobre esses modelos.

Voltando…

Tanto para o NaiveBayes quanto para a SVM utilizamos as implementações disponíveis no scikit-learn.

Criação do modelo de NaiveBayes
Criação do modelo de SVM

Após fazer a validação com o DataFrame de teste, percebemos que o modelo de NaiveBayes obteve uma acurácia de 60.90%, e o modelo de SVM 82.71%. A SVM se mostrou um modelo muito mais robusto nesse caso por conseguir lidar melhor com a diferenças entre os heterônimos.

Visualizando os resultados

É possível aplicar um algoritmo de redução de dimensionalidade no vetor tf-idf para melhor visualizar a diferença entre os 4 principais heterônimos (Alberto Caeiro, Ricardo Reis, Álvaro de Campos e Bernardo Soares).

Visualização do vetor tf-idf em 3 dimensões
Visualizações do vetor tf-idf para cada autor em duas dimensões

Conclusão

Nesse post, explicamos um pouco sobre como usamos corpus do Fernando Pessoa para aplicarmos técnicas de Classificação de Texto.

Assim como muitas pessoas utilizam a linguagem para manifestar sua criatividade, também podemos utilizar Processamento de Linguagem Natural para explorar aplicações criativas. Como já citado anteriormente, uma aplicação recente de PLN em literatura foi a tarefa de atribuição de autoria dos “Federalist Papers”. Indo um passo além, também existem aplicações de geração de texto com Redes Neurais Recorrentes utilizando obras de escritores conhecidos, como foi feito com o poeta e dramaturgo William Shakespeare.

Esperamos que vocês tenham gostado do texto! Se quiserem conhecer um pouco mais sobre o que fazemos no grupo, não deixem de seguir as nossas redes sociais: Facebook, Instagram, LinkedIn e, claro, acompanhar nossos posts no Medium.

Até a próxima!

--

--