Aprendizagem Profunda | Mestrado em Inteligência Artificial | Universidade do Minho | 2025/26
Classificação multi-classe de textos curtos (80–120 palavras) em cinco categorias — Human, Anthropic, Google, Meta e OpenAI — usando Deep Learning e LLMs via few-shot prompting.
- Ranking: 1.º lugar nas 3 submissões (entre 23–25 grupos).
- Melhor accuracy: 92.67% (stacking MLP sobre 3 LLMs).
| Submissão | Modelo A | Acc. A | Modelo B | Acc. B | Ranking |
|---|---|---|---|---|---|
| 1 | DNN NumPy | 71.33% | DNN PyTorch | 68.67% | 🥇 1.º / 25 |
| 2 | Claude Opus (few-shot, N=30) | 91.33% | DNN PyTorch | 72.67% | 🥇 1.º / 24 |
| 3 | Claude Opus (few-shot, N=40) | 88.00% | Gemini 3.1 Pro (few-shot, N=20) | 83.33% | 🥇 1.º / 24 |
Os rankings completos de todos os grupos encontram-se em docs/rankings.xlsx.
| Abordagem | Melhor Modelo | K-Fold CV | Teste |
|---|---|---|---|
| NumPy (from scratch) | DNN 128→64 | 94.49% | 75.37%¹ |
| PyTorch | BiGRU (h=256) | 94.72% | 76.84%¹ |
| Transformers | DistilBERT (Grid Search) | 96.15% | 77.26%¹ |
| LLM (few-shot) | Claude Opus 4.6 | — | 87.33%² |
| LLM (stacking) | MLP sobre 3 LLMs | — | 92.67%² |
¹ 475 textos de teste. ² 150 textos de teste (LOO-CV).
Os modelos treinados atingem >94% em validação cruzada mas ~77% no teste externo (mudança de domínio). Um meta-classificador (stacking MLP) sobre 3 LLMs atinge 92.67%, superando tanto modelos treinados como LLMs individuais.
📄 Relatório: Ver PDF do Relatório
Framework modular de Deep Learning implementada inteiramente em NumPy, sem qualquer biblioteca de ML/DL:
- Camadas: Dense (He init, L2), Dropout (inverted), ReLU, Softmax
- Otimizadores: SGD com Momentum, Adam (com bias correction)
- Features: TF-IDF (word 1–2 grams + char 2–4 grams) + 13 features estilísticas = 5013 features
- Treino: Mini-batch, Early Stopping, Stratified K-Fold (K=3) sobre 122k textos
- Inclui: Bag-of-Words, TF-IDF Vectorizer, StandardScaler, OneHotEncoder — tudo from scratch
DNNs Tabulares — 7 variantes (Wide, Narrow, Deep, LeakyReLU, ELU, Simple, VeryDeep) + Grid Search (27 configs)
Modelos Sequenciais:
- Embedding + DNN (128d, 256d) com masked mean pooling
- BiLSTM e BiGRU (h=128, h=256) bidirecionais, 2 camadas
- BiLSTM + GloVe (100d, 400k vetores) — frozen e fine-tuned
Transformers (HuggingFace):
- BERT, DistilBERT, RoBERTa — estratégias frozen vs. partial fine-tuning
- Grid Search: 27 configs (LR × Dropout × camadas descongeladas)
- Melhor: DistilBERT (lr=5e-5, drop=0.2, unfreeze=4) → 96.15% CV, 77.26% teste
- Mixed precision (FP16), checkpoints por fold
- Modelos: Claude Opus 4.6, Gemini 3.1 Pro, GPT-5.4, DeepSeek V3
- Ensemble: Weighted majority voting (pesos calibrados por accuracy)
- Stacking: Meta-classificador MLP (LOO-CV) sobre previsões dos 3 melhores LLMs → 92.67%
- Geração própria via APIs de 15 modelos (GPT-3.5/4o/4o-mini/5o-mini, Gemini 2.5 Pro/Flash, Gemma 1/2/3, Opus/Sonnet/Haiku, Llama 3/3.1/3.2)
- Textos humanos extraídos da Wikipedia (revisões pré-2021) via API, com limpeza de artefactos
- Geração few-shot — textos gerados imitando o estilo dos exemplos do professor, com paralelismo multi-thread
- Seleção combinatória — 180 combinações testadas com baseline LR + TF-IDF contra os exemplos do docente
- Dataset final: ~122.000 textos equilibrados pelas 5 classes
AP/
├── database/ # Datasets e geração de dados
│ ├── func/ # Scripts de processamento
│ │ ├── data.py # Geração de textos (APIs + Wikipedia)
│ │ ├── extend.py # Expansão incremental do dataset
│ │ ├── fewshot.py # Geração few-shot (multi-thread)
│ │ ├── dataset.py # Construção do dataset final
│ │ ├── test.py # Construção do dataset de teste combinado
│ │ └── list.py # Manutenção da lista de termos
│ ├── models/ # Textos gerados por cada modelo de IA
│ ├── resources/ # Ficheiros auxiliares (lista de termos, etc.)
│ ├── dataset.csv # Dataset principal de treino (~122k textos)
│ ├── dataset-samples.csv # Exemplos do professor (125 textos)
│ ├── dataset-subm{1,2,3}.csv # Textos das submissões (sem labels)
│ ├── dataset-subm{1,2,3}-labels.csv # Labels revelados pelo professor
│ └── dataset-test.csv # Dataset de teste combinado (475 textos)
│
├── src/ # Framework NumPy (from scratch)
│ ├── neuralnet.py # Classe NeuralNetwork (treino, avaliação)
│ ├── layers.py # Dense, Dropout
│ ├── activations.py # ReLU, Softmax
│ ├── optimizer.py # SGD com Momentum, Adam
│ ├── losses.py # Categorical Cross-Entropy
│ ├── logisticregression.py # Regressão Logística multi-classe (baseline)
│ ├── vectorizers.py # TF-IDF, BoW, StandardScaler, OneHotEncoder
│ └── utils.py # Pipeline de features, K-Fold, split
│
├── notebooks/ # Análise e treino
│ ├── Data.ipynb # EDA + seleção combinatória (180 combos)
│ ├── Numpy.ipynb # Modelos NumPy (6 modelos, K-Fold + teste)
│ ├── Pytorch.ipynb # PyTorch (15 modelos + Grid Search)
│ ├── Transformers.ipynb # Transformers (BERT, DistilBERT, RoBERTa)
│ ├── LLM.ipynb # Few-shot com Claude Opus
│ └── Ensemble.ipynb # Ensemble de 4 LLMs
│
├── Subm{1,2,3}/ # Submissões (notebooks + CSVs)
│ ├── subm{N}-g1-MIA-A.{ipynb,csv} # Modelo A
│ └── subm{N}-g1-MIA-B.{ipynb,csv} # Modelo B
│
├── docs/ # Documentação
│ ├── report.pdf # Relatório (LNCS, 10 páginas)
│ ├── rankings.xlsx # Rankings das submissões (todos os grupos)
│ └── presentation.md # Link para vídeo da apresentação
│
├── .env.example # Template para chaves de API
├── .gitignore
├── env.yml # Ambiente Conda
└── README.md
- Git instalado.
- Anaconda ou Miniconda instalado.
- Chaves de API (apenas necessário para geração de dados ou inferência via LLMs).
Configuração das Variáveis de Ambiente (.env)
Para executar os scripts de geração de dados (data.py, fewshot.py) ou os notebooks de LLM, é necessário configurar as chaves de API:
-
Na raiz do projeto, copie o ficheiro de exemplo:
cp .env.example .env
-
Preencha o
.envcom as chaves das APIs que pretende utilizar:OPENAI_API_KEY="sk-..." ANTHROPIC_API_KEY="sk-ant-..." GEMINI_API_KEY="AIza..." DEEPSEEK_API_KEY="sk-..."
⚠️ O ficheiro.envestá no.gitignore— nunca faça commit das suas chaves.
-
Clonar o repositório:
git clone https://github.com/Luismpso/AP.git cd AP -
Criar e ativar o ambiente:
conda env create -f env.yml conda activate AP
-
Configurar chaves de API (opcional):
cp .env.example .env # Editar .env com as suas chaves -
Gerar dados (opcional):
cd database/func python data.py # Gerar textos via APIs python extend.py # Expandir dataset python dataset.py # Combinar em dataset.csv
-
Treinar modelos:
cd ../../notebooks jupyter notebook Numpy.ipynb # Tarefa 2 jupyter notebook Pytorch.ipynb # Tarefa 3 jupyter notebook Tranformers.ipynb # Tarefa 3
-
Submissões (exemplo):
cd ../Subm1 jupyter notebook subm1-g1-MIA-A.ipynb
| Nome | Nº | |
|---|---|---|
| Luís Miguel Pereira Silva | PG60390 | pg60390@alunos.uminho.pt |
| Pedro Miguel S. A. Urbano dos Reis | PG59908 | pg59908@alunos.uminho.pt |
| Guilherme Lobo Pinto | PG60225 | pg60225@alunos.uminho.pt |
| Pedro Alexandre Silva Gomes | PG60289 | pg60289@alunos.uminho.pt |
Este trabalho é de cariz estritamente académico. Universidade do Minho, Escola de Engenharia, Departamento de Informática.