Skip to content

Luismpso/AP

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

165 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🔍 Deteção de Texto Gerado por IA

Python Status Rank License

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.


🏆 Conquistas

  • Ranking: 1.º lugar nas 3 submissões (entre 23–25 grupos).
  • Melhor accuracy: 92.67% (stacking MLP sobre 3 LLMs).

📊 Resultados

Rankings da Competição

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.

Comparação de Abordagens

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


⚙️ Implementações

Tarefa 2 — Modelos From Scratch (NumPy)

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

Tarefa 3 — Modelos PyTorch

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

LLMs — Few-Shot Prompting

  • 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%

🗃️ Construção dos Dados

  1. 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)
  2. Textos humanos extraídos da Wikipedia (revisões pré-2021) via API, com limpeza de artefactos
  3. Geração few-shot — textos gerados imitando o estilo dos exemplos do professor, com paralelismo multi-thread
  4. Seleção combinatória — 180 combinações testadas com baseline LR + TF-IDF contra os exemplos do docente
  5. Dataset final: ~122.000 textos equilibrados pelas 5 classes

📂 Estrutura do Repositório

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

🚀 Reprodução

Pré-requisitos

  • 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:

  1. Na raiz do projeto, copie o ficheiro de exemplo:

    cp .env.example .env
  2. Preencha o .env com 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 .env está no .gitignore — nunca faça commit das suas chaves.

Passos

  1. Clonar o repositório:

    git clone https://github.com/Luismpso/AP.git
    cd AP
  2. Criar e ativar o ambiente:

    conda env create -f env.yml
    conda activate AP
  3. Configurar chaves de API (opcional):

    cp .env.example .env
    # Editar .env com as suas chaves
  4. 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
  5. Treinar modelos:

    cd ../../notebooks
    jupyter notebook Numpy.ipynb       # Tarefa 2
    jupyter notebook Pytorch.ipynb     # Tarefa 3
    jupyter notebook Tranformers.ipynb # Tarefa 3
  6. Submissões (exemplo):

    cd ../Subm1
    jupyter notebook subm1-g1-MIA-A.ipynb

🎥 Apresentação

Watch Video


👥 Grupo 1 — MIA

Nome Email
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

📜 Licença

Este trabalho é de cariz estritamente académico. Universidade do Minho, Escola de Engenharia, Departamento de Informática.

About

🤖 Multi-class detection of AI-generated vs. human text in English, covering Google, Mistral, Meta, and OpenAI models.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors