Parla — Como vive? Do que se alimenta?

Matheus Fernandes
LABHacker
Published in
8 min readApr 8, 2019

--

O Parla surgiu como um experimento do Laboratório Hacker para desenvolver a capacidade técnica da equipe de desenvolvimento em um projeto cujo o foco fosse a visualização de dados e a aplicação de diferentes algoritmos, inclusive, envolvendo aprendizado de máquina. Além disso, um desafio, imposto pela própria equipe, era que o desenvolvimento fosse voltado para dispositivos móveis, coisa que não é muito comum de se dar importância em projetos de visualização de dados. Mas como encaramos esse desafio ficará para um próximo post, pois nesse vamos falar sobre os algoritmos que utilizamos!

De onde vêm os dados?

Antes de falar de todo o processamento que fizemos para resultar no que o Parla é hoje, é importante dizer de onde e como pegamos os dados.

Atualmente, você consegue obter os dados por meio da API de dados abertos da Câmara dos Deputados dentro de “Deputados/Discursos”. Entretanto, como a API da Câmara disponibiliza os discursos apenas por deputados, utilizamos um webservice interno, onde os dados vêm todos juntos, num único endpoint. Mas nem tudo foi mil maravilhas… Tivemos que “decifrar” boa parte dos campos! Você acredita que o gênero do autor do discurso fica no campo emails? Pois é… E se eu disser que o texto do discurso só vem em HTML e em um campo chamado companyteaser? Fora uma infinidade de campos generic1, generic2, generic3 e por aí vai. Nada disso impediu nosso trabalho, mas as coisas poderiam ter sido mais fáceis, não é mesmo?

Dos dados disponíveis dos discursos, utilizamos a transcrição do discurso, a indexação e o sumário feitos pelo Departamento de Taquigrafia (DETAQ) da Câmara, data e hora do discurso e a fase em que foi realizado. Do autor do discurso, utilizamos o nome, partido, estado, gênero e tipo de autor.

Precisamos analisar todo o texto dos discursos?

Não… Grande parte de um discurso é um texto que não possui muito valor para nossas análises. Por isso, antes de aplicar nossos algoritmos, realizamos um pré-processamento dos textos, que consiste em, no caso dos textos transcritos pelo DETAQ, retirar tudo que é referente à indicação de orador ou descrição de eventos durante o discursos (como “palmas” ou “pronunciamento encaminhado”, por exemplo). Além disso, removemos todas as palavras que não possuem valor semântico, conhecidas como stopwords (a, ao, aos, aquela, aquele e aquilo são exemplos), removemos todos os números e também retiramos palavras e expressões que são muito utilizadas no processo legislativo, mas que não possuem um valor significativo, como falas procedurais, leituras de atas, etc.

E mesmo depois de fazer esse processamento inicial, ainda podemos reduzir ainda mais a quantidade de palavras usadas para as análises! Você concorda que os termos Reforma da Previdência e Reforma Previdenciária querem dizer a mesma coisa? Então! Existe uma técnica chamada stemização (do inglês, stemming) que é usada para aproximar o máximo possível as palavras que, provavelmente, possuem o mesmo valor semântico. Esse processo consiste em reduzir uma palavra ao seu radical. Por exemplo, as palavras criminal e crime, não são idênticas, mas no fundo têm um significado muito parecido e possuem o mesmo radical: crim. Com isso podemos reduzir ainda mais o tamanho dos textos que serão analisados, fazendo com que o processamento seja mais otimizado e sem perder o valor semântico dos textos.

Vale ressaltar que esse processo de reduzir a palavra ao seu radical não necessariamente vai resultar na raiz exata. A língua portuguesa é bastante complexa e aplicar todas as regras e exceções do processo de reduzir um termo ao seu radical tornaria o algoritmo muito lento.

Como resumir quase 100 mil discursos (que só aumentam) ?

Parece um desafio interessante, não é mesmo? E é justamente esse o objetivo do Parla: mostrar o debate parlamentar de uma forma mais simplificada, sem ter que forçar o cidadão a ler todos os textos. Pra isso, aplicamos dois algoritmos, que serão explicados logo abaixo.

Saco de palavras

Esse algoritmo é relativamente simples, mas gerou um resultado bem interessante. Consiste basicamente em contar a frequência que cada palavra aparece dentro de um discurso. Simples né? Mas por quê não complicar um pouquinho?

O problema do saco de palavras é que muitas vezes as palavras que são mais frequentes em um texto não possuem muito valor quando estão sozinhas. Movimento e social, por exemplo, são palavras que não dizem muito, mas que, quando estão juntas, possuem um significado completamente diferente. Para evitar que isso aconteça na nossa análise, passamos a contabilizar também expressões de 1 a 5 palavras. Caso um mesmo conjunto de cinco palavras, por exemplo, apareça mais de duas vezes em um discurso, na mesma ordem, assumimos que esse conjunto vale como uma “única palavra” na análise, um 5-gram. O mesmo processo é realizado para os conjuntos de menos palavras, mas sempre que um n-gram é formado as palavras pertencentes a ele são removidas da análise do próximo n-gram, para evitar a duplicação de termos.

Quando avaliamos o resultado final dessa análise constatamos que a frequência de termos de apenas uma palavra é muito maior que as expressões maiores, a ponto de fazer com que os termos de 2 ou mais palavras nem apareçam nas visualizações. Isso fez com que tomássemos a decisão de remover os one-grams da análise.

Expressões como Reforma Previdência, Direitos Humanos e Aumento Combustíveis passaram a aparecer com mais frequência, agregando um valor maior para análise, já que passam uma informação completa a respeito do assunto. Entretanto, a remoção dos one-grams também fez com que termos maiores e sem muito sentido aparecessem, como “agentes comunitários saúde agentes combate” e “eis círculo virtuoso economia”. O que fez com que tomássemos a decisão de remover também os 4-grams e 5-grams da análise. E é esse o estado atual desse algoritmo no Parla, olha um exemplo de como ficou a análise do período de 1 de janeiro a 31 de dezembro de 2018:

Naive Bayes e Decision Tree

O saco de palavras é um algoritmo relativamente simples, então optamos por também adicionar uma forma um pouco mais refinada, utilizando aprendizado de máquina. Inclusive, nesse modelo também é utilizado o método do saco de palavras como parte do processamento!

A primeira diferença entre os resultados dos dois algoritmos é que, no saco de palavras, os temas aparecem de acordo com os discursos, são extraídos do próprio texto. Já utilizando Naive Bayes e Decision Tree os temas são fixados em 31, ou seja, independente do conteúdo dos discursos os hexágonos terão sempre os mesmos temas possíveis. Mas internamente, a diferença entres os dois algoritmos é bem maior!

Começando pelo pré-processamento, no Naive Bayes e Decision Tree existe uma outra etapa, na qual todo o discurso é dividido em sentenças. Fazemos isso porque é mais fácil classificar uma quantidade menor de texto do que um discurso muito grande. E para ambos modelos (Naive Bayes e Decision Tree) usamos o mesmo método para extração de features que serão usadas para comparar dois textos: saco de palavras. Isso, o mesmo saco de palavras que expliquei anteriormente, se diferenciando somente em, ao invés de contar quantas vezes uma palavra (ou termo) se repete, contar apenas se uma palavra está presente no texto, independente da quantidade.

Tanto o Naive Bayes quanto o Decision Tree são algoritmos de aprendizado supervisionado, o que quer dizer que eles precisam de um treinamento inicial, com dados previamente classificados, para que eles aprendam e consigam fazer uma predição de um novo texto. Em outras palavras, dizemos para o algoritmo que determinadas sentenças com certeza pertencem à determinadas classes, e analisando o saco de palavras de cada sentença de treinamento ele consegue dizer a qual uma nova sentença pertence. Lembrando que uma sentença sempre será classificada apenas como um tema!

Nossa primeira etapa de classificação é o Naive Bayes, um classificador probabilístico baseado no Teorema de Bayes e sua principal característica é que ele desconsidera a relação entre as features, que no nosso caso são as palavras. Por isso, recebe o nome de naive, que significa ingênuo em inglês. Você pode conferir esse post, que tem um texto bem explicativo, inclusive com exemplos de implementação.

Todos nós sabemos que nem tudo o que um deputado diz no plenário possui, realmente, um conteúdo válido. Isso se dá, muitas vezes, até por questões regimentais da Câmara. Por isso, dividimos a classificação de uma sentença em duas etapas: classificação de conteúdo e classificação temática. A primeira utiliza o Naive Bayes para predizer se uma sentença possui conteúdo ou não. “Nós não podemos ficar reféns de correntes que acham que podem falar muito, mas não respeitam o direito do outro de também expressar o seu pensamento.” é um exemplo de sentença que, apesar de ter um tamanho considerável, não tem muito significado, ou pelo menos não dentro dos 31 temas definidos. Uma vez que a frase é classificada como conteúdo, ela segue adiante e passa pelo classificador temático, caso contrário ela é descartada.

Para a classificação temática utilizamos o Decision Tree, ou Árvore de Decisão. Esse algoritmo “faz perguntas” sobre os dados até conseguir filtrar a informação o suficiente para fazer uma predição. E um grande exemplo desse algoritmo é o Akinator, aquele gênio que te faz uma série de perguntas e no final descobre em quem você está pensando. No caso dos discursos, as ramificações da árvore são definidas pelos sacos de palavras de todas as sentenças, eles são organizados de uma forma otimizada para que, quando receber um novo saco palavras o algoritmo consiga filtrar e predizer a qual tema pertence.

Mas claro que nem tudo são flores! Tivemos, e ainda temos, problemas com a acurácia do algoritmo por se tratar de um classificador com 31 classes. Inicialmente, nosso dataset de treinamento (conjunto de dados já classificados, usado para ensinar o algoritmo) era bem pequeno, algo em torno de 700 sentenças, e nosso classificador estava com uma precisão de, aproximadamente, 20% de acerto. Com uma porcentagem tão baixa só tínhamos duas opções: rever o modelo ou aumentar o dataset de treinamento. Nós fizemos os dois!

Com a ajuda do pessoal do Departamento de Taquigrafia, aumentamos um pouco nosso dataset e alteramos nosso modelo, adicionando uma etapa a mais. Agrupamos nossos dados já classificados em 31 temas em 14 macro-temas e a classificação temática passou a ser feita em dois níveis. O primeiro utilizando o Decision Tree para classificar a sentença dentro dos 14 macro-temas e a partir dessa classificação passamos para um Naive Bayes, para chegarmos aos 31 temas iniciais. Dessa forma, passamos a ter algo em torno de 40% de precisão no classificador macro-temático e os classificadores menores com uma média de 70%.

Ainda estava muito baixo e a medida que aumentávamos nosso dataset a precisão do primeiro modelo que fizemos respondia melhor que o classificador de macro-temas. Então chegamos à conclusão de que o problema inicial era apenas o tamanho dos nossos dados de treinamento, e focando somente em classificar mais sentenças, conseguimos chegar à uma precisão de 37%. Ainda não é o melhor dos mundos, mas percebemos que é apenas uma questão de quantidade e qualidade do treinamento. Veja o resultado desse algoritmo para o período de 01/01/2018 a 31/12/2018:

Pra onde vamos agora?

Essa é uma boa pergunta! O Parla foi criado para que a comparação entre diferentes algoritmos seja feita facilmente então uma primeira perspectiva seria a de adicionar novas análises, novos pontos de vista sobre os mesmos dados. Além disso, ainda temos muito a melhorar, principalmente no que diz respeito ao Naive Bayes/Decision Tree, talvez tentar uma abordagem utilizando Random Forest, que é um conjunto de Decision Trees que trabalham em conjunto para classificar uma sentença.

Bom, essa é a situação atual do Parla, espero que nossas experiências tenham sido uteis para você e até a próxima!

--

--

Matheus Fernandes
LABHacker

Engenheiro de Software, desenvolvedor back-end no LabHacker da Câmara dos Deputados e pythonista de coração.