Python

Artigo 38 — Processamento de Linguagem Natural (NLP) Já leu

13 min de leitura

Artigo 38 — Processamento de Linguagem Natural (NLP)
Processamento de Linguagem Natural é o campo da IA que lida com texto e fala humana — análise de sentimentos, classificação de documentos, extração de

Artigo 38 — Processamento de Linguagem Natural (NLP)

Prof. Ricardo Matos Módulo 7 · Data Science e Machine Learning · Artigo 38 de 52


Introdução

Processamento de Linguagem Natural é o campo da IA que lida com texto e fala humana — análise de sentimentos, classificação de documentos, extração de informações, tradução automática, chatbots e resumo automático. Python domina essa área com bibliotecas como NLTK, spaCy e a revolucionária biblioteca Transformers da Hugging Face, que democratizou o acesso a modelos de linguagem de última geração como BERT e GPT.


Instalação

pip install nltk spacy transformers torch
python -m spacy download pt_core_news_sm
python -m spacy download en_core_web_sm

Pré-processamento de Texto com NLTK

import nltk
from nltk.tokenize import word_tokenize, sent_tokenize
from nltk.corpus import stopwords
from nltk.stem import PorterStemmer, RSLPStemmer
from nltk.probability import FreqDist
import string

# Download dos recursos necessários
nltk.download("punkt")
nltk.download("stopwords")
nltk.download("punkt_tab")
nltk.download("rslp")

texto = """
Python é uma linguagem de programação incrível. Ela é amplamente utilizada
em ciência de dados, desenvolvimento web e inteligência artificial.
Aprender Python abre muitas portas no mercado de trabalho brasileiro.
"""


def preprocessar_texto(texto: str, idioma: str = "portuguese") -> dict:
    """Pipeline completo de pré-processamento."""

    # 1. Tokenização
    tokens_palavras  = word_tokenize(texto.lower(), language=idioma)
    tokens_sentencas = sent_tokenize(texto, language=idioma)

    # 2. Remoção de pontuação
    tokens_limpos = [
        t for t in tokens_palavras
        if t not in string.punctuation
    ]

    # 3. Remoção de stopwords
    stop_pt = set(stopwords.words(idioma))
    tokens_sem_stop = [
        t for t in tokens_limpos
        if t not in stop_pt
    ]

    # 4. Stemming (reduz à raiz)
    stemmer = RSLPStemmer()   # stemmer para português
    tokens_stem = [stemmer.stem(t) for t in tokens_sem_stop]

    # 5. Frequência
    freq = FreqDist(tokens_sem_stop)

    return {
        "tokens":          tokens_palavras,
        "sentencas":       tokens_sentencas,
        "sem_stopwords":   tokens_sem_stop,
        "stems":           tokens_stem,
        "frequencias":     freq.most_common(10),
        "vocabulario":     len(set(tokens_sem_stop)),
        "total_tokens":    len(tokens_palavras),
    }


resultado = preprocessar_texto(texto)
print(f"Total de tokens:  {resultado['total_tokens']}")
print(f"Vocabulário único: {resultado['vocabulario']}")
print(f"\nTokens sem stopwords:\n{resultado['sem_stopwords']}")
print(f"\nTop 10 palavras:\n{resultado['frequencias']}")
print(f"\nSentencas:\n{resultado['sentencas']}")

spaCy: NLP Industrial

spaCy é mais rápido e preciso que NLTK para tarefas em produção — oferece tokenização, POS tagging, NER e análise de dependências em uma única chamada:

import spacy

nlp_pt = spacy.load("pt_core_news_sm")
nlp_en = spacy.load("en_core_web_sm")


def analisar_com_spacy(texto: str, modelo=None):
    """Análise linguística completa com spaCy."""
    if modelo is None:
        modelo = nlp_pt

    doc = modelo(texto)

    print(f"Texto: {texto}\n")

    # Tokens com informações linguísticas
    print("=== Tokens ===")
    print(f"{'Token':15} {'Lema':15} {'POS':10} {'Dep':10} {'Stop':5}")
    print("-" * 60)
    for token in doc:
        print(f"{token.text:15} {token.lemma_:15} "
              f"{token.pos_:10} {token.dep_:10} {token.is_stop}")

    # Named Entity Recognition
    print("\n=== Entidades ===")
    for ent in doc.ents:
        print(f"  {ent.text:20} → {ent.label_} ({spacy.explain(ent.label_)})")

    # Sentenças
    print("\n=== Sentenças ===")
    for i, sent in enumerate(doc.sents, 1):
        print(f"  {i}. {sent.text.strip()}")

    # Chunks de substantivo
    print("\n=== Grupos Nominais ===")
    for chunk in doc.noun_chunks:
        print(f"  {chunk.text:20} ← {chunk.root.dep_}")

    return doc


texto_pt = (
    "O professor Ricardo Matos ensina Python em São Paulo "
    "desde 2020. A Microsoft e a Google utilizam Python "
    "extensivamente em seus produtos de IA."
)
doc = analisar_com_spacy(texto_pt)

Representação de Texto: Bag of Words e TF-IDF

from sklearn.feature_extraction.text import (
    CountVectorizer, TfidfVectorizer
)
import pandas as pd


corpus = [
    "Python é ótimo para ciência de dados",
    "Java é usado no desenvolvimento empresarial",
    "Python e R são linguagens de análise de dados",
    "Machine learning com Python é muito poderoso",
    "Desenvolvimento web com JavaScript e Python",
]

# Bag of Words
vectorizer_bow = CountVectorizer(
    max_features=20,
    stop_words=None,
    ngram_range=(1, 2)   # unigramas e bigramas
)
X_bow = vectorizer_bow.fit_transform(corpus)

print("=== Bag of Words ===")
print(f"Vocabulário: {vectorizer_bow.get_feature_names_out()}")
print(f"\nMatriz:\n{pd.DataFrame(X_bow.toarray(), columns=vectorizer_bow.get_feature_names_out())}")


# TF-IDF — Term Frequency × Inverse Document Frequency
vectorizer_tfidf = TfidfVectorizer(
    max_features=20,
    ngram_range=(1, 2),
    sublinear_tf=True    # aplica log na TF
)
X_tfidf = vectorizer_tfidf.fit_transform(corpus)

print("\n=== TF-IDF ===")
df_tfidf = pd.DataFrame(
    X_tfidf.toarray(),
    columns=vectorizer_tfidf.get_feature_names_out()
).round(3)
print(df_tfidf)

# Similaridade coseno entre documentos
from sklearn.metrics.pairwise import cosine_similarity

similaridades = cosine_similarity(X_tfidf)
print("\n=== Similaridade entre documentos ===")
df_sim = pd.DataFrame(
    similaridades,
    columns=[f"Doc{i}" for i in range(len(corpus))]
)
print(df_sim.round(3))

Análise de Sentimentos

from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.metrics import classification_report
from sklearn.model_selection import train_test_split
import numpy as np


# Dataset de reviews de alunos
reviews = [
    ("O curso é excelente, aprendi muito!", 1),
    ("Ótima didática, professor muito claro", 1),
    ("Conteúdo muito bem organizado e completo", 1),
    ("Superou minhas expectativas, recomendo", 1),
    ("Fantástico, mudou minha carreira", 1),
    ("Muito bom, exercícios práticos e relevantes", 1),
    ("Adorei cada aula, conteúdo incrível", 1),
    ("Melhor curso que já fiz, vale cada centavo", 1),
    ("Péssimo, não aprendi nada útil", 0),
    ("Muito ruim, explicações confusas", 0),
    ("Decepcionante, esperava mais conteúdo", 0),
    ("Não recomendo, material desatualizado", 0),
    ("Terrível, perda de tempo e dinheiro", 0),
    ("Frustrante, professor não responde dúvidas", 0),
    ("Horrível, conteúdo superficial demais", 0),
    ("Muito abaixo do esperado, não vale o preço", 0),
]

textos, labels = zip(*reviews)
textos = list(textos)
labels = list(labels)

X_tr, X_te, y_tr, y_te = train_test_split(
    textos, labels, test_size=0.3, random_state=42
)

# Pipeline completo: TF-IDF + Classificador
pipeline_sentimento = Pipeline([
    ("tfidf", TfidfVectorizer(
        ngram_range=(1, 2),
        max_features=500,
        sublinear_tf=True
    )),
    ("clf", LogisticRegression(C=1.0, max_iter=1000))
])

pipeline_sentimento.fit(X_tr, y_tr)
y_pred = pipeline_sentimento.predict(X_te)

print("=== Análise de Sentimentos ===")
print(classification_report(
    y_te, y_pred,
    target_names=["Negativo", "Positivo"]
))

# Testando com novas frases
novas_frases = [
    "Curso muito bem estruturado e didático",
    "Não gostei, muito caro para pouco conteúdo",
    "Razoável, mas poderia ter mais exercícios",
]

for frase in novas_frases:
    pred  = pipeline_sentimento.predict([frase])[0]
    prob  = pipeline_sentimento.predict_proba([frase])[0]
    label = "Positivo" if pred == 1 else "Negativo"
    conf  = max(prob)
    print(f"  {label:10} ({conf:.1%}) — {frase}")

Word Embeddings com Word2Vec

from gensim.models import Word2Vec
import nltk

# pip install gensim
corpus_frases = [
    ["python", "linguagem", "programacao", "dados"],
    ["java", "linguagem", "programacao", "empresarial"],
    ["machine", "learning", "python", "algoritmos"],
    ["dados", "analise", "estatistica", "python"],
    ["web", "desenvolvimento", "javascript", "html"],
    ["inteligencia", "artificial", "redes", "neurais"],
    ["banco", "dados", "sql", "consultas"],
    ["api", "rest", "flask", "fastapi", "python"],
]

modelo_w2v = Word2Vec(
    sentences=corpus_frases,
    vector_size=100,    # dimensão dos embeddings
    window=5,           # janela de contexto
    min_count=1,
    workers=4,
    epochs=100
)

print("=== Word2Vec ===")
print(f"\nVetor de 'python': shape={modelo_w2v.wv['python'].shape}")

# Palavras mais similares
similares = modelo_w2v.wv.most_similar("python", topn=5)
print(f"\nPalavras mais similares a 'python':")
for palavra, score in similares:
    print(f"  {palavra:15}: {score:.4f}")

# Analogia: machine - python + java = ?
try:
    analogia = modelo_w2v.wv.most_similar(
        positive=["machine", "java"],
        negative=["python"],
        topn=3
    )
    print(f"\nAnalogias:")
    for p, s in analogia:
        print(f"  {p}: {s:.4f}")
except KeyError as e:
    print(f"Token não encontrado: {e}")

Hugging Face Transformers

from transformers import pipeline
import torch


# Sentiment Analysis em português
print("=== Análise de Sentimentos com Transformers ===")
analisador = pipeline(
    "sentiment-analysis",
    model="lxyuan/distilbert-base-multilingual-cased-sentiments-student",
    device=0 if torch.cuda.is_available() else -1
)

frases = [
    "Python é incrível para ciência de dados!",
    "Esse framework é muito lento e frustrante.",
    "O curso foi razoável, nada extraordinário.",
]

for frase in frases:
    resultado = analisador(frase)[0]
    print(f"  {resultado['label']:10} ({resultado['score']:.1%}) — {frase}")
# Classificação Zero-Shot — sem treinamento específico
print("\n=== Zero-Shot Classification ===")
classificador = pipeline(
    "zero-shot-classification",
    model="facebook/bart-large-mnli"
)

texto = "O governo anunciou novas medidas para controlar a inflação."
categorias = ["economia", "política", "tecnologia", "esporte", "saúde"]

resultado = classificador(texto, categorias)
print(f"Texto: {texto}")
for label, score in zip(resultado["labels"][:3], resultado["scores"][:3]):
    print(f"  {label:15}: {score:.1%}")
# Question Answering
print("\n=== Question Answering ===")
qa = pipeline(
    "question-answering",
    model="deepset/roberta-base-squad2"
)

contexto = """
Python foi criado por Guido van Rossum e lançado em 1991.
É uma linguagem de programação de alto nível, interpretada e de propósito geral.
Python enfatiza a legibilidade do código e usa indentação significativa.
A versão mais recente é Python 3.12, lançada em outubro de 2023.
"""

perguntas = [
    "Quem criou o Python?",
    "Quando o Python foi lançado?",
    "Qual é a versão mais recente do Python?",
]

for pergunta in perguntas:
    resposta = qa(question=pergunta, context=contexto)
    print(f"  P: {pergunta}")
    print(f"  R: {resposta['answer']} (conf: {resposta['score']:.1%})\n")
# Geração de texto com GPT-2
print("=== Geração de Texto ===")
gerador = pipeline(
    "text-generation",
    model="gpt2",
    device=0 if torch.cuda.is_available() else -1
)

prompt = "Python is a powerful programming language that"
resultado = gerador(
    prompt,
    max_new_tokens=60,
    num_return_sequences=2,
    temperature=0.8,
    do_sample=True,
    pad_token_id=50256
)

for i, r in enumerate(resultado, 1):
    print(f"\n[Geração {i}]")
    print(r["generated_text"])

Sumarização Automática

from transformers import pipeline

sumarizador = pipeline(
    "summarization",
    model="facebook/bart-large-cnn"
)

artigo = """
Machine learning is a subset of artificial intelligence that provides systems
the ability to automatically learn and improve from experience without being
explicitly programmed. Machine learning focuses on the development of computer
programs that can access data and use it to learn for themselves.
The process begins with observations or data, such as examples, direct experience,
or instruction, so that computers can look for patterns in data and make better
decisions in the future. The primary aim is to allow the computers to learn
automatically without human intervention or assistance and adjust actions accordingly.
"""

resumo = sumarizador(
    artigo,
    max_length=80,
    min_length=30,
    do_sample=False
)
print("=== Sumarização ===")
print(f"Original: {len(artigo.split())} palavras")
print(f"Resumo:   {len(resumo[0]['summary_text'].split())} palavras")
print(f"\n{resumo[0]['summary_text']}")

Exemplo Completo: Sistema de Classificação de Tickets

from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.multiclass import OneVsRestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import classification_report
import numpy as np


# Dataset de tickets de suporte
tickets = [
    ("Não consigo acessar minha conta, esqueci a senha", "acesso"),
    ("Sistema travando ao abrir o módulo de notas", "bug"),
    ("Como faço para exportar o boletim em PDF?", "duvida"),
    ("Meu pagamento não foi processado", "financeiro"),
    ("Erro 500 ao tentar salvar dados do aluno", "bug"),
    ("Preciso redefinir minha senha urgente", "acesso"),
    ("Qual o prazo para lançamento de notas?", "duvida"),
    ("Cobrança duplicada no cartão de crédito", "financeiro"),
    ("Botão de login não funciona no Chrome", "bug"),
    ("Como adicionar um novo aluno ao sistema?", "duvida"),
    ("Login bloqueado após várias tentativas", "acesso"),
    ("Fatura com valor incorreto", "financeiro"),
    ("Relatório gerando dados errados", "bug"),
    ("Como funciona o cálculo da média?", "duvida"),
    ("Preciso de acesso para novo professor", "acesso"),
]

textos, categorias = zip(*tickets)
textos     = list(textos)
categorias = list(categorias)

le = LabelEncoder()
y  = le.fit_transform(categorias)

X_tr, X_te, y_tr, y_te = train_test_split(
    textos, y, test_size=0.3, random_state=42
)

pipeline_tickets = Pipeline([
    ("tfidf", TfidfVectorizer(
        ngram_range=(1, 2),
        max_features=1000,
        sublinear_tf=True
    )),
    ("clf", LogisticRegression(
        C=5.0,
        max_iter=1000,
        multi_class="multinomial"
    ))
])

pipeline_tickets.fit(X_tr, y_tr)
y_pred = pipeline_tickets.predict(X_te)

print("=== Classificador de Tickets ===")
print(classification_report(
    y_te, y_pred,
    target_names=le.classes_
))

# Classificando novos tickets
novos_tickets = [
    "Sistema não carrega após atualização",
    "Preciso de nota fiscal do pagamento",
    "Como resetar a senha do administrador?",
    "Dúvida sobre o calendário de provas",
]

print("Classificação de novos tickets:")
probs = pipeline_tickets.predict_proba(novos_tickets)
for ticket, prob in zip(novos_tickets, probs):
    idx_melhor  = np.argmax(prob)
    categoria   = le.classes_[idx_melhor]
    confianca   = prob[idx_melhor]
    print(f"\n  Ticket: {ticket}")
    print(f"  Categoria: {categoria} ({confianca:.1%})")

    # Top 3 categorias prováveis
    top3 = np.argsort(prob)[::-1][:3]
    print(f"  Distribuição: " +
          ", ".join(f"{le.classes_[i]}={prob[i]:.0%}" for i in top3))

Resumo

  • Pré-processamento de texto inclui tokenização, remoção de stopwords, stemming e lematização
  • spaCy oferece análise linguística industrial: POS, NER, dependências e chunks em uma pipeline
  • TF-IDF pondera termos pela frequência no documento e raridade no corpus — melhor que BoW puro
  • Análise de sentimentos combina TF-IDF com classificadores clássicos de forma eficiente
  • Word2Vec aprende representações densas de palavras capturando relações semânticas
  • Transformers da Hugging Face entregam state-of-the-art em classificação, QA e geração de texto
  • Modelos pré-treinados multilíngues funcionam em português sem necessidade de re-treinamento
  • Zero-shot classification classifica textos em categorias nunca vistas durante o treinamento

Referências e Leituras Complementares

  • NLTK — documentação oficial — https://www.nltk.org/
  • spaCy — documentação oficial — https://spacy.io/api
  • Hugging Face Transformers — https://huggingface.co/docs/transformers/
  • Hugging Face Hub — modelos em português — https://huggingface.co/models?language=pt
  • Gensim — Word2Vec — https://radimrehurek.com/gensim/
  • BIRD, Steven; KLEIN, Ewan; LOPER, Edward. Natural Language Processing with Python. O'Reilly Media, 2009. — disponível gratuitamente em https://www.nltk.org/book/
  • TUNSTALL, Lewis; VON WERRA, Leandro; WOLF, Thomas. Natural Language Processing with Transformers. O'Reilly Media, 2022. — referência definitiva sobre uso prático da biblioteca Transformers.

Prof. Ricardo Matos — Dominando o Python em 1 Ano · Artigo 38 de 52 Próximo: Artigo 39 — Visão Computacional com OpenCV e PIL


you asked

Sim


claude response

Dominando o Python em 1 Ano

Comentários

Mais em Python

Artigo 47 — Design Patterns em Python
Artigo 47 — Design Patterns em Python

Design Patterns — padrões de projeto — são soluções reutilizáveis para proble...

WebSockets e Comunicação em Tempo Real em Python (Ver se é duplicidade)
WebSockets e Comunicação em Tempo Real em Python (Ver se é duplicidade)

HTTP é excelente para o modelo requisição-resposta — o cliente pergunta, o se...

FastAPI: APIs modernas com tipagem e documentação automática
FastAPI: APIs modernas com tipagem e documentação automática

FastAPI é o framework web que mais cresceu no ecossistema Python nos últimos...