Detectando fake news com scikit-learn
Este tutorial de scikit-learn vai guiar você na construção de um classificador de fake news com a ajuda de modelos bayesianos.
· 15 min leer
Explore com IA
Relacionado
Tutorial
Tutorial de manipulação de dados categóricos de aprendizado de máquina com Python
Aprenda os truques comuns para lidar com dados categóricos e pré-processá-los para criar modelos de aprendizado de máquina!
Tutorial
Entendendo data drift e model drift: detecção de drift em Python
Navegue pelos riscos do model drift e confira nosso guia prático de monitoramento de data drift.
Tutorial
Tutorial de análise de sentimentos com NLTK para iniciantes
Tutorial de análise de sentimentos com NLTK (Natural Language Toolkit) em Python. Aprenda a criar e desenvolver análises de sentimentos usando Python. Siga etapas específicas para realizar a mineração e análise de textos e fazer o processamento de linguagem natural.


Detectar as chamadas “fake news” não é tarefa simples. Primeiro, é preciso definir o que é fake news — algo que ganhou conotação política. Se você conseguir definir ou concordar com um conceito, então precisa coletar e rotular corretamente notícias reais e falsas (de preferência sobre temas semelhantes para evidenciar melhor as diferenças). Depois de coletar, é preciso encontrar boas features para distinguir notícias falsas de reais.
Para um mergulho mais profundo nesse tema, recomendo o post do Miguel Martinez-Alvarez: “How can Machine Learning and AI Help Solve the Fake News Problem”.
Na mesma época em que li o post do Miguel, encontrei um artigo no Open Data Science sobre como construir um detector de fake news com modelos bayesianos. O autor ainda criou um repositório com o dataset rotulado de exemplos reais e falsos. Fiquei curioso para saber se eu conseguiria reproduzir os resultados com facilidade e, em seguida, entender o que o modelo havia aprendido.
Neste tutorial, você vai acompanhar parte da minha exploração inicial e ver se consegue construir um detector de fake news que funcione!
Dica: se você quer aprender mais sobre fundamentos de Processamento de Linguagem Natural (NLP), vale conferir o curso Natural Language Processing Fundamentals in Python.
Exploração de dados
Para começar, sempre dê uma olhada rápida nos dados para sentir o conteúdo. Para isso, use um DataFrame do Pandas e verifique o shape, o head e aplique as transformações necessárias.
Extraindo os dados de treino
Agora que o DataFrame está mais próximo do que você precisa, separe os rótulos e monte os conjuntos de treino e teste.
Neste notebook, decidi focar no texto mais longo do artigo. Como eu sabia que usaria bag-of-words e TF-IDF (Term Frequency–Inverse Document Frequency) para extrair features, essa parecia uma boa escolha. Textos mais longos tendem a trazer palavras e características distintas para diferenciar as notícias reais das falsas.
Construindo classificadores com vetorizadores
Agora que você tem os dados de treino e teste, pode construir os classificadores. Para avaliar se as palavras e tokens dos artigos impactam a classificação entre notícia real e falsa, começamos usando
CountVectorizereTfidfVectorizer.No exemplo, há um limite máximo
.7definido no TF-IDFtfidf_vectorizercom o argumentomax_df. Isso remove palavras que aparecem em mais de 70% dos artigos. Além disso, o parâmetrostop_wordsembutido remove stop words em inglês dos dados antes de vetorizá-los.Existem muitos outros parâmetros — você pode conferir todos na documentação do scikit-learn para
TfidfVectorizereCountVectorizer.Com os vetores prontos, você pode inspecionar as features geradas, armazenadas em
count_vectorizeretfidf_vectorizer.Há algum problema visível? (Sim!)
Claramente existem comentários, medidas ou outras palavras sem sentido, além de artigos em vários idiomas no dataset. Normalmente, você deveria investir mais tempo no pré-processamento e na remoção de ruído, mas como este tutorial é apenas uma prova de conceito rápida, vamos ver se o modelo consegue superar o ruído e classificar corretamente apesar desses problemas.
Intermezzo: contagem vs. TF-IDF
Fiquei curioso para saber se os vetorizadores de contagem e de TF-IDF extraíram tokens diferentes. Para comparar as features, você pode trazer as informações de volta para um DataFrame e fazer comparações em Python com facilidade.
Rodando as células abaixo, dá para ver que ambos extraíram os mesmos tokens, mas com pesos diferentes. Alterar
max_dfemin_dfdo TF-IDF provavelmente mudaria o resultado e levaria a features diferentes em cada um.5 rows × 56922 columns
5 rows × 56922 columns
Comparando modelos
Hora de treinar e testar os modelos.
Vamos começar com um favorito do NLP, o
MultinomialNB. Você pode usá-lo para comparar TF-IDF com bag-of-words. Minha intuição era que bag-of-words (ouCountVectorizer) funcionaria melhor com esse modelo. (Para entender a distribuição multinomial e por que ela funciona melhor com inteiros, confira esta explicação sucinta de um curso de estatística da UPenn.)Pessoalmente, acho Matrizes de Confusão mais fáceis de ler e comparar, então usei a documentação do scikit-learn para construir versões legíveis (valeu, open source!). A matriz de confusão mostra os rótulos corretos na diagonal principal (do canto superior esquerdo ao inferior direito). As outras células mostram rótulos incorretos, os famosos falsos positivos e falsos negativos. Dependendo do problema, um deles pode ser mais crítico. Por exemplo, em fake news, é mais importante não rotular notícias reais como falsas? Se sim, talvez valha ponderar a métrica de acurácia para refletir essa preocupação.
Além de Matrizes de Confusão, o scikit-learn oferece várias formas de visualizar e comparar modelos. Uma bem popular é usar a curva ROC. Há muitos outros recursos de avaliação disponíveis no módulo metrics.
E de fato, sem nenhum ajuste de parâmetro, o conjunto vetorizado por contagem
count_trainteve desempenho visivelmente melhor que os vetores TF-IDF!Testando modelos lineares
Há muitos materiais mostrando que modelos lineares funcionam muito bem com vetorizadores TF-IDF (veja word2vec para classificação, a referência de SVM na análise de texto do scikit-learn e outros).
Então é só usar SVM, certo?
Recentemente, assisti à aula do Victor Lavrenko sobre classificação de texto, em que ele compara classificadores Passive Aggressive com SVMs lineares para texto. Vamos testar essa abordagem (que tem ganhos de velocidade relevantes, mas desvantagens de aprendizado “permanente”) com o dataset de fake news.
Uau!
Impressiona. A matriz de confusão ficou diferente e o modelo classificou um pouco melhor as fake news. Podemos testar se ajustar o
alphadoMultinomialNBgera resultados comparáveis. Você também pode usar ajuste de parâmetros com grid search para uma busca mais ampla.Nem tanto… Neste ponto, pode ser interessante ajustar parâmetros em todos os classificadores, ou explorar outros classificadores bayesianos do scikit-learn. Você também pode testar uma Support Vector Machine (SVM) para ver se supera o Passive Aggressive.
Mas estou mais curioso para saber o que o modelo Passive Aggressive realmente aprendeu. Vamos à introspecção.
Fazendo introspecção dos modelos
Então, fake news resolvida, certo? Conseguimos 93% de acurácia — missão cumprida.
Claro que não. Eu, no mínimo, fico cauteloso com esses resultados, dado o quanto de ruído vimos nas features. Há uma ótima resposta no StackOverflow com uma função muito útil para encontrar os vetores que mais afetam os rótulos. Ela só funciona para classificação binária (2 classes), o que é perfeito aqui, já que temos apenas FAKE e REAL.
Usando o classificador de melhor desempenho com o dataset TF-IDF (
tfidf_vectorizer) e o Passive Aggressive (linear_clf), inspecione os 30 principais vetores para fake e real:Você também pode fazer isso de forma bem direta com poucas linhas de Python, juntando os coeficientes às features e olhando o topo e a base da lista.
Fica claro que há certas palavras que indicam intenção política e fonte entre as principais features de fake (como corporate e establishment).
Também dá para ver que as notícias reais usam mais formas do verbo “say”, provavelmente porque em jornais e publicações jornalísticas as fontes são citadas diretamente (“A chanceler alemã Angela Merkel said…”).
Para extrair a lista completa do classificador atual e analisar cada token (ou comparar facilmente entre classificadores), você pode exportar assim:
Intermezzo: HashingVectorizer
Outro vetorizador usado às vezes para classificação de texto é o
HashingVectorizer. Ele consome menos memória e é mais rápido (por ser esparso e usar hashes em vez de tokens), mas é mais difícil de inspecionar. Você pode ler mais sobre prós e contras doHashingVectorizerna documentação do scikit-learn.Vale testar e comparar seus resultados com os outros vetorizadores. Ele vai bem — melhor que o TF-IDF com
MultinomialNB(o que já era esperado pelos mesmos motivos deCountVectorizer) —, mas não supera o TF-IDF com o algoritmo linear Passive Aggressive.Conclusão
Será que o seu experimento de classificador de fake news foi um sucesso? Definitivamente não.
Mas você pôde explorar um dataset novo, testar alguns modelos de classificação em NLP e inspecionar o quão bem eles funcionaram? Sim.
Como esperado desde o início, definir fake news com bag-of-words ou TF-IDF é uma abordagem simplista — ainda mais com um dataset multilíngue cheio de ruído. Se você não tivesse olhado o que o modelo realmente aprendeu, poderia achar que ele capturou algo significativo. Então, lembre-se: sempre faça introspecção dos seus modelos (na medida do possível!).
Fico curioso para saber se você encontra outras tendências nos dados que eu possa ter deixado passar. Vou publicar um post comparando como diferentes classificadores se comportam em relação às features mais importantes no meu blog. Se você pesquisar e achar algo interessante, compartilhe nos comentários ou fale comigo no Twitter (sou @kjam).
Espero que você tenha se divertido explorando um novo dataset de NLP comigo!
Dê uma olhada no Python Machine Learning: Scikit-Learn Tutorial da DataCamp.