Aula 2, Stopwords

Esta aula trata das stopwords, as palavras muito frequentes e pouco informativas, como artigos e preposições. Vamos entender por que costuma valer a pena removê-las, observar a lei de Zipf nos dados e filtrar as perguntas dos alunos que tokenizamos na aula anterior.

Depois de quebrar o texto em tokens, surge uma pergunta natural, todas as palavras têm o mesmo valor? A resposta é não. Em qualquer texto, um punhado de palavras como o, a, de, que e em domina a contagem, mas diz muito pouco sobre o assunto. Essas são as stopwords, e tratá-las bem é um passo simples que melhora muitas tarefas de NLP.

Seguindo o fio do módulo, vamos pegar os tokens das perguntas de alunos e remover essas palavras de pouca substância, deixando à mostra os termos que de fato indicam o tema, como derivada, matriz ou Python. No caminho, vamos esbarrar em um padrão fascinante e universal da linguagem, a lei de Zipf, que explica por que tão poucas palavras concentram tanta frequência.


Objetivos

Ao final desta aula, você deve ser capaz de:

  • Explicar o que são stopwords e por que elas têm baixo poder de discriminação.
  • Remover stopwords de um texto tokenizado.
  • Reconhecer a lei de Zipf na distribuição de frequências das palavras.
  • Avaliar quando remover stopwords ajuda e quando pode atrapalhar.

Teoria

Stopwords são palavras que aparecem com altíssima frequência e carregam pouca informação sobre o conteúdo. Artigos, preposições, conjunções e pronomes são os exemplos típicos. Como elas surgem em praticamente todos os documentos, não ajudam a distinguir um assunto de outro, e por isso muitas tarefas as descartam para reduzir ruído e tamanho.

A remoção é direta. Mantemos uma lista de stopwords do idioma e filtramos os tokens que estão nela. O efeito é concentrar a representação nos termos de conteúdo. Vale notar que a lista certa depende do idioma e, às vezes, do domínio, e que existem listas prontas, por exemplo no NLTK, mas montar a sua própria ajuda a entender o que está acontecendo.

flowchart LR
    T["Tokens: como, faço, a, derivada"] --> F[Filtro de stopwords]
    L["Lista: como, a, de, que..."] --> F
    F --> R["Restam: faço, derivada"]

Há um pano de fundo estatístico bonito aqui. A lei de Zipf, observada por George Zipf, diz que a frequência de uma palavra é aproximadamente inversamente proporcional à sua posição em um ranking de frequência. A palavra mais comum aparece cerca do dobro da segunda, o triplo da terceira, e assim por diante. É por isso que um número pequeno de stopwords responde por uma fatia enorme do total de palavras.

Explicação Intuitiva

Imagine destacar as ideias principais de um texto com um marca-texto. Você não pinta os artigos e as preposições, pinta os substantivos e verbos que carregam o sentido. Remover stopwords é automatizar esse instinto, apagar o que é só liga entre as ideias e manter o que aponta para o assunto.

Mas atenção, nem sempre as stopwords são descartáveis. Em uma frase como não entendi, a palavra não é curtinha e comum, porém muda completamente o sentido. Por isso a remoção de stopwords é uma ferramenta, não uma regra cega. Em tarefas como análise de sentimento, jogar fora certas palavrinhas pode custar caro.

Explicação Matemática

A lei de Zipf pode ser escrita de forma simples. Se ordenarmos as palavras da mais para a menos frequente e chamarmos de $r$ a posição no ranking, a frequência $f$ de uma palavra é aproximadamente

\[f(r) \approx \frac{C}{r},\]

em que $C$ é uma constante que depende do tamanho do texto. Em palavras, a frequência cai rápido conforme descemos no ranking. Quando colocamos frequência e ranking em escala logarítmica, essa relação vira aproximadamente uma reta descendente, uma assinatura fácil de reconhecer.

A consequência prática é direta. Como poucas palavras no topo do ranking concentram grande parte das ocorrências, e essas palavras são justamente as stopwords, removê-las encolhe bastante o total de tokens com perda mínima de informação sobre o tema.

Exemplo Prático

Vamos retomar as perguntas de alunos da aula passada, contar a frequência de cada token e visualizar como poucas palavras dominam, exatamente como a lei de Zipf prevê. Em seguida, removemos as stopwords e observamos o que sobra, que são os termos realmente ligados a cálculo, álgebra e programação.

Esse texto filtrado é uma representação mais enxuta e mais informativa, e será a entrada das aulas de Bag of Words e TF-IDF. O código está no notebook notebooks/modulo-03/02-stopwords.ipynb, então abra-o ao lado para acompanhar.

Código Comentado

import re
from collections import Counter

perguntas = [
    "Como faço a derivada de uma função?",
    "Qual é a regra da cadeia na derivada?",
    "Como resolvo um sistema linear com matrizes?",
    "O que é um autovetor de uma matriz?",
    "Como declaro uma função em Python?",
    "O que é um laço de repetição em Python?",
]

# Uma lista pequena de stopwords do português, só para o exemplo.
STOPWORDS = {
    "a", "o", "as", "os", "um", "uma", "de", "da", "do", "em", "na", "no",
    "que", "é", "e", "com", "qual", "como", "para", "por",
}


def tokenizar(texto):
    return re.findall(r"\w+|[^\w\s]", texto.lower(), re.UNICODE)


def remover_pontuacao(tokens):
    return [t for t in tokens if t.isalnum()]


# Conta a frequência de todas as palavras, antes de remover stopwords.
contagem = Counter()
for p in perguntas:
    contagem.update(remover_pontuacao(tokenizar(p)))

print("Palavras mais frequentes (lei de Zipf em ação):")
for palavra, freq in contagem.most_common(6):
    print(f"  {palavra:12} {freq}")


def remover_stopwords(tokens):
    return [t for t in tokens if t not in STOPWORDS]


print("\nAntes e depois de remover stopwords:")
for p in perguntas[:3]:
    tokens = remover_pontuacao(tokenizar(p))
    print("  original:", tokens)
    print("  filtrado:", remover_stopwords(tokens))

Ao rodar, repare que as palavras do topo da contagem são quase todas stopwords, o que confirma a intuição de Zipf. Depois do filtro, cada pergunta fica reduzida aos seus termos de conteúdo, e perguntas de temas diferentes passam a ter pouca ou nenhuma palavra em comum, o que é ótimo para distinguir os assuntos mais adiante.

Exercícios

1) Conceitual: O que torna uma palavra uma boa candidata a stopword? Por que ela ajuda pouco a distinguir assuntos? 2) Conceitual: Dê um exemplo de tarefa em que remover stopwords seria uma má ideia, e explique por quê. 3) Prático: Amplie a lista de stopwords e veja quantos tokens a mais são removidos do conjunto de perguntas. 4) Prático: Conte a frequência das palavras de um texto maior, à sua escolha, e verifique se o topo do ranking é dominado por stopwords. 5) Extensão: Pesquise a lei de Zipf e tente reproduzir, com um texto grande, o gráfico de frequência por ranking em escala logarítmica.

Projeto da Aula

Investigue o efeito das stopwords sobre o vocabulário. A entrega é um experimento que mede o tamanho do vocabulário e o total de tokens das perguntas antes e depois da remoção de stopwords, e que lista as palavras mais frequentes nos dois casos.

Considere o projeto pronto quando você tiver os números de antes e depois e um parágrafo comentando quanto a remoção encolheu o texto e por que isso quase não afeta a capacidade de identificar o tema. Esse texto filtrado é o que vamos transformar em vetores nas próximas aulas.

Leituras Recomendadas

  • Seções sobre stopwords e pré-processamento em Manning e colegas, Introduction to Information Retrieval.
  • Capítulos sobre frequência de palavras em Jurafsky e Martin, Speech and Language Processing.
  • Material do NLTK sobre listas de stopwords em diferentes idiomas, em Bird e colegas, Natural Language Processing with Python.

Referências Científicas

As referências abaixo são reais e estão registradas em references/referencias.bib. As chaves entre parênteses são as do BibTeX.

  • Zipf, G. K. (1949). Human Behavior and the Principle of Least Effort. Addison-Wesley. (zipf1949effort)
  • Manning, C. D., Raghavan, P., e Schütze, H. (2008). Introduction to Information Retrieval. Cambridge University Press. (manning2008ir)
  • Jurafsky, D., e Martin, J. H. (2009). Speech and Language Processing, 2ª edição. Pearson Prentice Hall. (jurafsky2009slp)
  • Bird, S., Klein, E., e Loper, E. (2009). Natural Language Processing with Python. O’Reilly. (bird2009nltk)