TP1: O Classificador de Habilidades

Redes Neurais, NLP e MLOps (Fases 1 e 2 do Pipeline)

Conteúdo de estudo sobre TP1: O Classificador de Habilidades para a disciplina de Inteligência Artificial II (Prof. Aléssio M. Jr).
Data de Publicação

08/09/2026

Data de Modificação

04/09/2026

🧭 Por que este TP existe?

Volte ao metadata.yaml do exercício “Divisão” que você viu na página de Visão Geral. Repare no campo skills:

skills:
  - "matematica"
  - "io"

Esses rótulos dizem quais habilidades cognitivas um aluno precisa dominar para resolver aquele exercício. Hoje, quem classifica essas skills é o professor, manualmente. Isso é lento, subjetivo e não escala para centenas de exercícios.

A missão do TP1 é construir uma Rede Neural Clássica que leia o texto bruto de um enunciado de programação e preveja automaticamente quais skills ele exige. Esse modelo será o motor das Fases 1 e 2 do Pipeline WOKDEX.

Dica👥 Repositórios e Composição das Equipes

O acompanhamento dos grupos registrados no GitLab, links diretos dos repositórios e a listagem de alunos com sinalizadores de status estão disponíveis em Grupos do TP1 (2026-2).


📖 Leitura Obrigatória (Fundamentação)

Antes de programar, vocês precisam ler e entender estes dois artigos científicos. Eles serão a base do Draft 1 na seção de Trabalhos Relacionados.

Artigo 1: Kim, Y. (2014). “Convolutional Neural Networks for Sentence Classification”. arXiv:1408.5882

Por que ler: É exatamente o que vocês vão construir — uma rede neural que recebe uma frase e classifica em categorias. O paper tem apenas 6 páginas e mostra como vetorizações de texto (Word2Vec, TF-IDF) alimentam um classificador profundo. A arquitetura descrita é a referência mais citada do mundo para classificação de texto com Deep Learning.

Artigo 2: Feng, Z. et al. (2020). “CodeBERT: A Pre-Trained Model for Programming and Natural Language”. arXiv:2002.08155

Por que ler: Enquanto o artigo anterior trata de classificação de textos genéricos, este mostra que existe um campo de pesquisa inteiro dedicado a aplicar NLP especificamente em código-fonte e enunciados de programação. Vocês não vão usar o CodeBERT em si (ele é pesado demais para o escopo do TP), mas entender que o problema que vocês estão atacando já é estudado por grandes labs (Microsoft Research) dá lastro científico ao Draft 1.


📚 O que é uma Skill no WOKDEX e no Dataset?

As habilidades (skills) representam os conceitos algorítmicos e estruturas de dados necessários para resolver um exercício.

Para o TP1, trabalharemos com as 25 Skills/Tópicos mais representativos da amostra (que cobrem 94% do volume de problemas e incluem desde estruturas básicas até paradigmas avançados como Grafos e Backtracking):

# Skill / Tópico Ocorrências no Dataset Exemplo Típico
1 Array (Vetores) 1.626 “Encontre o par de elementos que soma o alvo”
2 String (Textos) 683 “Verifique se a palavra é um palíndromo”
3 Hash Table (Tabela Hash / Dicionário) 589 “Conte a frequência de cada caractere em \(O(N)\)
4 Dynamic Programming (Programação Dinâmica) 508 “Calcule o número de formas de subir uma escada”
5 Math (Matemática) 503 “Converta números romanos para inteiros”
6 Sorting (Ordenação) 391 “Ordene o array por frequência decrescente”
7 Greedy (Algoritmos Gulosos) 366 “Distribua doces minimizando o total”
8 Binary Search (Busca Binária) 259 “Encontre a raiz quadrada inteira em \(O(\log N)\)
9 Depth-First Search (Busca em Profundidade / DFS) 242 “Percorra todos os caminhos válidos da árvore”
10 Matrix (Matrizes / Arrays 2D) 216 “Rotacione uma imagem \(N \times N\) em 90 graus”
11 Bit Manipulation (Manipulação de Bits) 212 “Conte o número de bits 1 na representação binária”
12 Breadth-First Search (Busca em Largura / BFS) 193 “Encontre o menor caminho no grafo”
13 Prefix Sum (Soma de Prefixos) 184 “Calcule a soma de um intervalo em \(O(1)\)
14 Tree (Árvores) 182 “Calcule a profundidade máxima da árvore”
15 Two Pointers (Dois Ponteiros) 181 “Remova duplicatas de um vetor ordenado in-place”
16 Simulation (Simulação) 165 “Simule o movimento de um robô no grid”
17 Heap (Priority Queue) (Heap / Fila de Prioridade) 164 “Encontre o K-ésimo maior elemento”
18 Counting (Contagem de Elementos) 145 “Conte elementos com frequências específicas”
19 Stack (Pilhas) 138 “Valide se parênteses e colchetes estão balanceados”
20 Graph (Grafos) 133 “Detecte ciclos ou caminhos em grafos direcionados”
21 Sliding Window (Janela Deslizante) 130 “Maior substring contígua sem caracteres repetidos”
22 Binary Tree (Árvore Binária) 129 “Inverta ou reconstrua uma árvore binária”
23 Enumeration (Enumeração) 112 “Gere todas as combinações válidas de 3 dígitos”
24 Design (Projeto de Estruturas) 94 “Implemente um LRU Cache ou Fila usando Pilhas”
25 Backtracking (Retrocesso / Busca Exaustiva) 87 “Resolva o problema das N Rainhas ou Sudoku”

[!IMPORTANT] Formulação do Problema: Classificação Multi-Label
Um mesmo problema pode exigir múltiplas skills simultâneas (por exemplo, um exercício pode ter rótulos ['Array', 'Sorting', 'Two Pointers']).
Portanto, sua Rede Neural NÃO deve usar Softmax na saída!
Utilize: 1. Camada de saída com 25 neurônios e função de ativação sigmoid. 2. Função de perda (loss): binary_crossentropy. 3. Binarização dos alvos: MultiLabelBinarizer da biblioteca scikit-learn.


📦 O Dataset Oficial (leetcode_problems_pt)

A base oficial de dados para o TP1 é o LeetCode Problems Dataset Bilíngue, disponibilizado em formato tabular (CSV) e estruturado (JSON), com 2.830 enunciados completos em Português (PT-BR).

Nota🔗 Links para Acesso e Download

🐍 Snippet de Carga Rápida (Python / Pandas)

O Aluno A (Engenheiro de Dados) pode iniciar o pipeline com o seguinte fluxo:

import pandas as pd
import ast
from sklearn.preprocessing import MultiLabelBinarizer

# 1. Carregar dataset oficial
df = pd.read_csv("trabalho/database/leetcode_problems_pt.csv")

# 2. Selecionar features de entrada e target
# X: Texto do enunciado em Português (título + descrição completa contendo exemplos e restrições)
X_text = (df["title_pt"].fillna("").astype(str) + "\n\n" + df["description_pt"].fillna("").astype(str))

# 3. Tratar a coluna de tópicos (que vem como string de lista)
def parse_topics(val):
    if pd.isna(val): return []
    try: return ast.literal_eval(val) if isinstance(val, str) else val
    except: return []

df["topics_list"] = df["topics"].apply(parse_topics)

# 4. Filtrar para as Top 25 Skills
TOP_25_SKILLS = [
    "Array", "String", "Hash Table", "Dynamic Programming", "Math",
    "Sorting", "Greedy", "Binary Search", "Depth-First Search", "Matrix",
    "Bit Manipulation", "Breadth-First Search", "Prefix Sum", "Tree", "Two Pointers",
    "Simulation", "Heap (Priority Queue)", "Counting", "Stack", "Graph",
    "Sliding Window", "Binary Tree", "Enumeration", "Design", "Backtracking"
]

df["target_skills"] = df["topics_list"].apply(
    lambda topics: [t for t in topics if t in TOP_25_SKILLS]
)

# 5. Binarizar alvos para Multi-Label (Y terá shape: [N, 25])
mlb = MultiLabelBinarizer(classes=TOP_25_SKILLS)
Y = mlb.fit_transform(df["target_skills"])
print("Total de classes mapeadas:", len(mlb.classes_))
print(f"Shape final de Y: {Y.shape}")

Data Limite de Entrega (Checkpoint 1): 12/09 (Sexta-feira)

Valor: 10 Pontos (5 em Grupo, 5 Individual)

[!IMPORTANT] Sobre o timing do NLP: A vetorização de texto (TF-IDF, Word2Vec) será coberta na Aula 9 (Módulo 2 — Embeddings). Vocês podem começar a construir toda a infraestrutura (Keras, FastAPI, Docker, testes) usando o conhecimento dos Labs 04–08 enquanto aguardam essa aula para fechar o pipeline de dados do Aluno A. O deadline foi calibrado para que vocês tenham pelo menos 1 semana após a Aula 9.

[!TIP] Baseline Obrigatório: No Draft 1, o grupo deve comparar a performance da Rede Neural contra um baseline simples (ex: TF-IDF + Logistic Regression / LinearSVC com OneVsRestClassifier). A tabela comparativa (Precision, Recall, F1-Macro, tempo de treino) é item obrigatório da avaliação.


👥 A Divisão de Tarefas na Equipe (4 Alunos em 2 Duplas)

Para garantir que o trabalho seja executado de forma fluida ao longo dos 20 dias, a carga horária estimada é de 10 a 15 horas de dedicação individual por aluno (~3 a 4 horas por semana). A equipe divide-se em duas duplas complementares:

┌────────────────────────────────────────────────────────┐
│                   EQUIPE DE 4 ALUNOS                   │
├───────────────────────────┬────────────────────────────┤
│  🔬 DUPLA 1: DADOS & ML   │  ⚙️ DUPLA 2: ENGENHARIA    │
│  (O Cérebro Matemático)   │  (A Casca MLOps / Docker)  │
├───────────────────────────┼────────────────────────────┤
│  Aluno A: Dados & NLP     │  Aluno C: Backend FastAPI  │
│  Aluno B: Redes Neurais   │  Aluno D: DevOps & Pytest  │
└───────────────────────────┴────────────────────────────┘

🔬 Dupla 1: Ciência e Dados (O Cérebro) — ~10 a 15h por aluno

Esta dupla é focada no pré-processamento de linguagem natural (NLP) em português e no treinamento da Rede Neural. O output final da dupla é o pipeline serializado (vectorizer.pkl / mlb.pkl), o modelo treinado (modelo_skills.keras) e as métricas de convergência.

  • Aluno A (Engenheiro de Dados):
    • Dedicação: ~10–12 horas.
    • Tarefas: Carregar leetcode_problems_pt.csv, limpar os enunciados em português (description_pt), tratar as 25 skills com MultiLabelBinarizer, criar e serializar a vetorização de texto (ex: TfidfVectorizer(max_features=5000, ngram_range=(1,2))), e gerar a divisão estratificada Treino/Validação/Teste (80/10/10).
  • Aluno B (Engenheiro de Machine Learning):
    • Dedicação: ~12–15 horas.
    • Tarefas: Construir e treinar o Baseline (ex: LogisticRegression / LinearSVC OvR), construir a Rede Neural Keras (camadas Densas, Dropout 0.3-0.5, saída 25 neurônios Sigmoid + binary_crossentropy), calibrar o limiar de decisão (\(\tau\)), gerar gráficos de loss/épocas e calcular o F1-Score Macro e Micro.

⚙️ Dupla 2: Engenharia de Software e MLOps (A Casca) — ~10 a 15h por aluno

Esta dupla pega o modelo exportado pela Dupla 1 e constrói um microsserviço moderno, conteinerizado e testado, pronto para ser consumido pelo Agente do TP3.

  • Aluno C (Dev Backend Python / FastAPI):
    • Dedicação: ~10–12 horas.
    • Tarefas: Criar a API FastAPI, definir contratos estritos de entrada e saída com Pydantic (PredictRequest, PredictResponse), carregar os artefatos (modelo_skills.keras e vectorizer.pkl) na inicialização da aplicação (usando lifespan), e implementar os endpoints POST /predict e GET /health.
  • Aluno D (DevOps, QA e Docker):
    • Dedicação: ~10–12 horas.
    • Tarefas: Escrever o Dockerfile otimizado e docker-compose.yml, configurar a suite de testes automatizados com pytest (mínimo 5 testes), configurar a pipeline de CI no GitLab (.gitlab-ci.yml), e garantir que a API suba limpa em qualquer máquina com um único comando docker run.

[!TIP] 🤝 Dinâmica de Pareamento (Pair Programming) e Desenvolvimento Não-Bloqueante:
A Dupla 2 não deve esperar a Dupla 1 concluir o treinamento da rede neural para começar a trabalhar. Usem a abordagem de Contrato Primeiro (API-First / Contract-Driven): 1. No primeiro dia, a equipe alinha os modelos Pydantic (PredictRequest e PredictResponse). 2. A Dupla 2 cria um modelo simulado (mock) que devolve predições estáticas e constrói toda a API FastAPI, o Dockerfile e a suite de pytest em paralelo. 3. Os membros de cada dupla devem praticar pareamento contínuo, code reviews e ajuda mútua para manter o fluxo de entrega sem gargalos.


🔌 A API que você vai construir

O produto final de engenharia do TP1 é uma API REST conteinerizada. Abaixo está o contrato exato:

Requisição: POST /predict

{
  "enunciado": "Dada uma lista de inteiros nums e um inteiro target, retorne os índices dos dois números cuja soma seja igual a target."
}

Resposta esperada:

{
  "skills": [
    { "skill": "Array", "confidence": 0.94 },
    { "skill": "Hash Table", "confidence": 0.88 },
    { "skill": "Two Pointers", "confidence": 0.72 }
  ],
  "model_version": "v1.0",
  "input_length": 132
}

[!IMPORTANT] No TP3, o Agente Autônomo vai chamar esta API como uma ferramenta (predict_skills()). Se a sua API não estiver de pé e respondendo neste formato, o agente do TP3 não funcionará. É por isso que o Docker é obrigatório.


📝 Relatório Técnico no README.md (Documentação do TP1)

Para não sobrecarregar a equipe com formatação de artigos nesta fase inicial, a entrega do TP1 é 100% focada em Engenharia, Código e Métricas Técnicas.

O grupo deve documentar de forma clara e estruturada no próprio README.md do repositório GitLab (que servirá de base direta para o Artigo Final no TP3):

  1. Trabalhos Relacionados e Fundamentação:
    • Contextualizar brevemente os artigos base (Kim 2014 para CNN/NLP e CodeBERT para representação de código).
  2. Metodologia Preditiva (Dupla 1):
    • Justificativa da Formulação Multi-Label: Explicar matematicamente por que a saída usa Sigmoid independente por neurônio + binary_crossentropy em vez de Softmax.
    • Arquitetura da Rede: Tabela com as camadas da rede neural, número de neurônios, funções de ativação, taxa de Dropout e otimizador.
  3. Resultados e Tabela Comparativa Obrigatória (Dupla 1 e 2):
    • Tabela comparando o Baseline (TF-IDF + Logistic Regression / SVM) contra a Rede Neural (Keras):
Modelo Precision (Macro) Recall (Macro) F1-Score (Macro) F1-Score (Micro) Tempo de Treino
Baseline (TF-IDF + Regressão Logística OvR) ~2s
Rede Neural Keras (Dense + Dropout) ~45s
  1. Análise de Desbalanceamento, Threshold \(\tau\) e o Abismo Semântico (Dupla 1):
    • Gráfico de convergência (Loss de Treino vs. Validação).
    • Discussão do Abismo Semântico (Semantic Gap): Analisar criticamente quais das 25 classes foram mais fáceis/difíceis. Por que classes sintáticas como String ou Tree apresentam F1 mais elevado do que paradigmas abstratos como Dynamic Programming ou Greedy?
    • Efeito do limiar de decisão \(\tau\) dinâmico no F1-Score das classes minoritárias (ex: Backtracking).
  2. Engenharia e Arquitetura MLOps (Dupla 2):
    • Diagrama ou descrição da conteinerização Docker, latência média da rota POST /predict (em milissegundos) e testes unitários.

🧪 Sugestões de Testes Automatizados Obrigatórios (pytest)

O Aluno D (DevOps) deve implementar, no mínimo, a seguinte suite de testes com pytest (arquivo tests/test_api.py):

# Função de Teste O que deve verificar
1 test_api_health A rota GET /health responde HTTP 200 e status "ok"
2 test_predict_valid_input POST /predict com enunciado válido retorna HTTP 200 e campos skills, model_version, input_length
3 test_skills_in_top25 Todas as skills retornadas na lista pertencem estritamente às 25 classes válidas
4 test_confidence_range O valor de confidence de cada skill prevista está rigorosamente no intervalo \([0.0, 1.0]\)
5 test_empty_input_validation Enunciado vazio ("" ou whitespace) retorna HTTP 422 (validação Pydantic)
6 test_predict_deterministic Duas chamadas com o mesmo texto produzem as mesmas predições

📊 Rubrica de Avaliação Detalhada (8 Pontos)

Nota Individual (4 pts)

Critério Pontos Detalhes
Commits individuais na branch correta 1 Avaliado via Git Blame (evidência de autoria)
Entrega técnica individual funcionando 2 Pipeline do Aluno A OU Rede do Aluno B OU FastAPI do Aluno C OU Docker/Testes do Aluno D
Qualidade e organização do código 1 Boas práticas, docstrings, código modular e limpo

Nota do Grupo (4 pts)

Critério Pontos Detalhes
API integrada responde no formato correto 1 docker run + curl POST /predict funcional
Performance da Rede Neural (F1-Score Macro) 1 Veja escala progressiva calibrada abaixo
Relatório Técnico no README.md completo 2 Tabela comparativa baseline vs. rede, matriz de confusão, discussão do abismo semântico

Escala Progressiva de Performance (F1-Score Macro)

Nível F1-Score Macro Pontuação Critério de Engenharia
Mínimo \(\ge 35\%\) 0.3 pt Supera o baseline ingênuo / classe majoritária
Bom \(\ge 50\%\) 0.7 pt Rede Keras regularizada (Dropout, limiar \(\tau\) calibrado)
Excelente \(\ge 65\%\) 1.0 pt Otimização avançada de hiperparâmetros ou análise exemplar de erro

[!NOTE] Por que a régua de F1-Macro é calibrada nesta faixa?
Lembre-se do Abismo Semântico (Semantic Gap): os enunciados usam metáforas narrativas (“Alice divide doces”) e a técnica algorítmica (DP, Guloso) é uma abstração matemática implícita. Um F1-Macro de 50–65% em 25 classes multi-label desbalanceadas é um resultado de engenharia sólido e realista. A profundidade da sua análise crítica no README.md tem peso decisivo na pontuação do grupo.


📅 Cronograma Sugerido (4 Semanas)

Para não acumular trabalho e perder a data de entrega, sugerimos o seguinte ritmo para a equipe:

Período Foco da Equipe Meta da Semana
Semana 1 Pesquisa e Setup Leitura do artigo (Kim 2014), divisão de papéis, setup do repositório GitLab e script base de TF-IDF.
Semana 2 Modelagem Treinamento do baseline (SVM/LR) e primeira versão da Rede Neural (Keras).
Semana 3 Engenharia MLOps Otimização do F1-Score, criação da API em FastAPI e criação do Dockerfile.
Semana 4 Qualidade e README Escrita dos testes pytest, validação final, preenchimento do relatório no README.md e Merge Request final.

✅ Checklist de Entrega — TP1


🔬 Adendo IC — Golden Benchmark e Estudo de Ablação Textual (Opcional)

Esta seção é exclusiva para equipes da Trilha de Iniciação Científica (IC). As equipes regulares podem ignorá-la. Se uma equipe IC desistir da trilha, o adendo já executado conta como +1 ponto bônus na nota regular do TP1.

Enquanto as equipes regulares treinam seus classificadores na divisão padrão, as equipes IC atuam como o Comitê Científico de Validação do ecossistema WOKDEX, conduzindo experimentos aprofundados que fundamentarão os artigos da disciplina.

O que fazer

  1. Curadoria do Golden Benchmark Set (100 Problemas):
    • Selecionar e auditar minuciosamente uma amostra estratificada de 100 problemas do dataset leetcode_problems_pt.csv, cobrindo as 25 skills e os níveis Easy, Medium e Hard.
    • Verificar a fidelidade do enunciado em português e validar a consistência das skills anotadas.
    • Este conjunto será o teste cego do professor para avaliar as APIs de todas as equipes no Demoday.
  2. Estudo de Ablação Textual (TF-IDF vs. Embeddings em Português):
    • Comparar o desempenho da Rede Neural sob diferentes representações vetoriais de texto em PT-BR:
      1. TF-IDF esparso (unigramas + bigramas).
      2. paraphrase-multilingual-MiniLM-L12-v2 (Sentence-Transformers).
      3. BERTimbau (neuralmind/bert-base-portuguese-cased).
      4. text-embedding-3-small (OpenAI).
    • Tabular o F1-Macro e a latência de inferência de cada abordagem.
  3. Análise de Sensibilidade ao Desbalanceamento:
    • Testar o impacto de Class Weights e limiares de decisão dinâmicos (\(\tau_i\)) nas classes com menor suporte estatístico (ex: Backtracking com 87 amostras vs. Array com 1.626).

Entregáveis IC-TP1

[!TIP] Os dados gerados neste adendo comporão diretamente a seção experimental do Artigo 1 da Disciplina (Classificação Semântica de Enunciados em Língua Portuguesa para Educação em Computação).

De volta ao topo