# Model Card — AIDA P0 | | | |---|---| | **Modelo** | AIDA P0 (`AIDA-2.0`) | | **Versão do release** | `aida-p0-1.0.0` | | **Tarefa** | classificação binária de imagem: fotografia real × imagem gerada/manipulada por IA | | **Threshold oficial** | `0.48158617244389096` | | **Convenção** | POSITIVO = IA. `FN = IA → REAL` é o erro crítico | | **Idioma da saída** | português | | **Pesos** | **não incluídos neste repositório** | | **Licença do código** | MIT | | **Licença dos pesos** | **`LICENSE_UNKNOWN_REVIEW_REQUIRED`** — ver `LICENSES.md` | --- ## AIDA Core P0 | | | |---|---| | **Status** | Production Champion | | **Backbone visual** | `ViT-B-32-quickgelu` | | **Representação** | 512 dimensões | | **Pipeline** | Visual Expert + Forensics + Rigid/Real Evidence + Fusion | | **Classificação** | REAL / IA | | **Threshold** | `0.48158617244389096` | | **Pesos** | **não incluídos neste repositório** — ver abaixo | **Os pesos do modelo P0 não acompanham este repositório.** Eles estão publicados no Space que hospeda a API — `AIDAON/aida-api` — e é lá que as inferências de produção acontecem. Estarem publicados **não** é autorização de uso e **não** resolve a pendência de licença: a situação dos pesos continua `LICENSE_UNKNOWN_REVIEW_REQUIRED`, com Q1 e Q2 `PENDENTE_DE_DECISAO`. Ver `LICENSES.md`. Este repositório publica o **código**, a **metodologia**, a **arquitetura**, as **métricas** e as **limitações** do detector. Ele **não** publica os pesos, e por isso **não roda inferência sozinho** — ver *Quick Start*. ## Model Summary O AIDA é um detector de imagens geradas por IA construído como **fusão de três sensores independentes** sobre uma mesma imagem. Ele não olha metadados nem marcas d'água: decide pelo conteúdo do pixel. O P0 é o *champion* congelado do projeto, promovido em 2026-08-27. Desde então **catorze etapas de investigação** (D a N) tentaram superá-lo e nenhuma conseguiu de forma defensável — fine-tuning do backbone, fusão aprendida, detector por patches, remoção de subpopulações do treino e reposicionamento do limiar foram todos testados e todos rejeitados. Este release publica o P0 exatamente como ele está, com os números que ele de fato produz. **O número que deve ser citado** é o do `teste_externo_882`: **FNR 0,1852 / FPR 0,0972 / MCC 0,7235**. Mas leia a seção *Dataset Shift* antes de usar qualquer um deles como expectativa de desempenho. ## Intended Use * **triagem assistida** — ordenar um lote de imagens por suspeita, para que uma pessoa revise as mais suspeitas primeiro; * **pesquisa** — linha de base reprodutível para trabalhos sobre detecção de imagem sintética e sobre *dataset shift* em detectores; * **educação** — demonstrar concretamente o que um detector desses acerta, erra, e por quê; * **auditoria do próprio projeto** — reproduzir os números publicados. O AIDA é mais útil quando o custo de um falso positivo é **uma revisão humana**, não uma consequência para alguém. ## Out-of-Scope Use **Não use o AIDA para:** * acusar uma pessoa de fraude, plágio, falsificação ou má conduta; * decidir sozinho sobre emprego, nota escolar, crédito, seguro, imigração, moderação punitiva ou qualquer processo com consequência jurídica; * peritagem forense ou produção de prova — o AIDA **não é** ferramenta forense e não produz cadeia de custódia; * atestar que uma imagem é **autêntica**. "REAL" aqui significa "compatível com as fotografias que o modelo viu no treino", não "verdadeira", "não editada" ou "não manipulada"; * detectar deepfake de rosto, troca de face ou manipulação local — o modelo foi treinado para *imagem inteira gerada*, e a única etapa que testou edição local (PATCH) não generalizou; * processar imagem de domínio muito diferente do treino (satélite, médica, microscopia, documento escaneado, arte digital, captura de tela de texto) esperando os números publicados. **Não use em produção com decisão automática.** O FPR pode passar de 45% dependendo do tipo de fotografia (ver *Dataset Shift*). ## Architecture ``` ARQUIVO └─ normalização de entrada (lado máximo 1024 px, JPEG q92, em memória) │ ├── B2 FORENSE 846 características em 7 blocos → RandomForest → Platt ├── B3 CLIP ViT-B-32-quickgelu congelado → cabeça linear → Platt └── B5 RIGID 5 passes do CLIP com ruído → logística → Platt │ ├── FUSÃO B4: média aritmética simples dos três scores ├── CALIBRAÇÃO: Platt sobre a média └── DECISÃO: score_ia ≥ 0.48158617244389096 → IA ``` A **normalização de entrada** não é detalhe: os três sensores foram treinados sobre imagens de lado máximo 1024 px e JPEG q92. Sem levar a entrada a esse domínio, uma foto de câmera de 4000 px chega aos extratores com uma assinatura de compressão que nenhuma imagem de treino tinha, e o indicador `qualidade_blocagem` sai de ~0,92 para ~1,00 — região praticamente vazia no treino. O efeito medido foi empurrar fotografias reais para "IA". ## Sensors ### B3 — CLIP (`ViT-B-32-quickgelu`, pesos `openai`) Encoder visual **congelado** (nenhum gradiente), embedding de 512 dimensões normalizado, seguido de uma cabeça `Linear(512→256) → ReLU → Dropout(0,3) → Linear(256→1)` e calibração Platt. É o **sensor mais forte e também o mais problemático**. A ETAPA G mediu que a amplitude de FPR entre domínios é **0,72 para o B3**, contra 0,18 do B2 e 0,16 do B5 — quase toda a heterogeneidade do detector vem dele. Os pesos do backbone **não acompanham este release**: o `open_clip` os baixa na primeira execução. ### B2 — Forense 846 características em sete blocos (espacial, espectral, textura/ruído, FFT 5×5, LSB, laplaciano/DoG/TSR, forense avançada, qualidade), sobre um `RandomForestClassifier`, com calibração Platt. É o sensor **mais estável entre domínios** e o único que não depende de rede neural pré-treinada. ### B5 — RIGID *Training-free*. Passa a imagem pelo CLIP cinco vezes, quatro delas com ruído gaussiano (σ = 0,02), e mede a **estabilidade** do embedding: imagens geradas tendem a ser mais sensíveis à perturbação que fotografias. A estatística resultante entra numa regressão logística com calibração Platt. Foi o sensor que **não se deslocou** sob mudança de domínio na ETAPA F (δ de Cliff −0,019, contra −0,703 do B3) — os dois sensores *treinados* deslocam, o *training-free* não. ## Fusion O score final é a **média aritmética simples** dos três scores calibrados, seguida de uma calibração Platt: ``` score_ia = sigmoide( 10.223586107747385 × média(clip, forense, rigid) − 4.932178246308984 ) ``` A média foi escolhida sobre fusões aprendidas por um motivo medido: com 546 amostras de validação (~89 cenas), o meta-modelo campeão anterior ficou **não monotônico** — aumentar `score_clip` de 0,30 para 0,70 *reduzia* a probabilidade final. A média é monotônica por construção e tem zero parâmetros ajustados. A ETAPA E testou uma fusão aprendida: ela melhora a **ordenação** (TPR a 1% de FPR sobe de 0,4947 para 0,6852 no 882) e **não converte isso em decisões** (FN 70 → 80 com FPR casado). Não foi promovida. ## Threshold ``` 0.48158617244389096 ``` Três coisas que este número **é**, e uma que ele **não é**: * saiu do **índice de Youden sobre o conjunto de validação** do champion *anterior*, em 2026-08-13; * foi **deliberadamente congelado** na promoção do P0 (decisão "P0-4"), para que a comparação isolasse mudança de modelo de mudança de ponto de operação. `b4_ensemble.config_calibracao.estrategia_limiar` registra `"fixo"`; * nunca foi reestimado sobre os scores do P0. **Não é** um ótimo. A ETAPA N auditou a curva inteira e mediu que o limiar de MCC máximo é **0,2901** na validação, **0,5202** no External 882 e **0,8626** no External V2 — amplitude de 0,5725, mais de metade da escala. Cada população pede um ponto de operação diferente. A mesma etapa mediu que **mexer no limiar não resolve**: no External 882, o melhor total de erros que *qualquer* política de limiar alcança é **118 contra os 119** do limiar atual. Por isso ele não foi alterado. Uma **banda inconclusiva** `[0,321586 ; 0,641586]` acompanha a política. O release a reporta em `na_banda_inconclusiva` e `decisao_politica`, mas **`classe` é a decisão pura pelo limiar** — que é como todas as métricas abaixo foram calculadas. ## Training * **4.475 imagens** do acervo próprio da equipe, divididas em treino (2.501), validação (546), teste interno (546) e teste externo (882); * lado REAL: fotografias da própria equipe. **~32% do lado REAL é retrato** — isso importa, e volta na seção *Dataset Shift*; * lado IA: imagens geradas pela equipe em **OpenAI**, **Google Gemini** e **ByteDance**, mais um bloco de proveniência não totalmente identificada; * cada cena entra com até 6 variantes (1 canônica + 5 capturas de tela em resoluções diferentes) da **mesma** fotografia. A divisão é por *cena*, nunca por imagem, para não vazar a mesma foto entre treino e teste; * semente 42; backbone CLIP **congelado** (nenhum gradiente). **Nenhuma imagem de treino ou avaliação é redistribuída neste release.** O que a documentação **não** afirma, porque não foi verificado: que o acervo seja representativo de fotografia em geral. A ETAPA G mostrou que ele não é. ## Evaluation Todas as métricas abaixo foram medidas com o threshold oficial, sobre scores congelados. Convenção: POSITIVO = IA. ### Conjuntos próprios | conjunto | n | REAL | IA | TP | TN | FP | FN | FPR | FNR | MCC | bal.acc | F1 | ROC-AUC | PR-AUC | |---|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|---:| | `validacao_546` | 546 | 306 | 240 | 204 | 273 | 33 | 36 | 0,1078 | 0,1500 | 0,7432 | 0,8711 | 0,8553 | 0,9517 | 0,9398 | | `teste_546` | 546 | 306 | 240 | 207 | 278 | 28 | 33 | 0,0915 | 0,1375 | 0,7729 | 0,8855 | 0,8716 | 0,9345 | 0,9436 | | **`teste_externo_882`** | 882 | 504 | 378 | 308 | 455 | 49 | 70 | **0,0972** | **0,1852** | **0,7235** | 0,8588 | 0,8381 | 0,9154 | 0,9125 | `validacao_546` **escolheu o threshold** — o número dela é otimista por construção. `teste_externo_882` é o conjunto de decisão: cenas que nunca entraram em treino, validação, calibração, escolha de limiar ou seleção de modelo. ### Conjuntos independentes | conjunto | n | REAL | IA | FP | FN | FPR | FNR | MCC | ROC-AUC | |---|---:|---:|---:|---:|---:|---:|---:|---:|---:| | `external_v2` | 900 | 540 | 360 | 252 | 1 | **0,4667** | 0,0028 | 0,5567 | 0,9836 | | `pool_publico` (ETAPA G) | 2.433 | 2.433 | 0 | 840 | — | **0,3453** | — | — | — | `external_v2`: 150 cenas novas, interseção zero com tudo. `pool_publico`: 2.433 fotografias reais públicas (MS-COCO 1.503 + ImageNet 930), 100% REAL. ### TPR em regime de FPR baixo (`teste_externo_882`) | alvo de FPR | TPR | |---|---| | 0,5% | **NÃO IDENTIFICÁVEL** (504 negativos não resolvem esse regime) | | 1% | 0,4947 | | 2% | 0,5767 | | 5% | 0,7328 | | 10% | 0,8175 | | no threshold oficial (FPR 0,0972) | 0,8148 | Ou seja: **exigir 1% de FPR custa metade das detecções.** ## Dataset Shift **Esta é a seção mais importante deste documento.** O FPR do AIDA **não é um número**. Ele depende fortemente da população: | população | o que é | FPR | |---|---|---:| | `teste_546` | acervo próprio | **0,0915** | | `teste_externo_882` | acervo próprio, cenas inéditas | **0,0972** | | `pool_publico` | 2.433 fotografias reais públicas (COCO + ImageNet) | **0,3453** | | `external_v2` | 900 imagens novas, 87,8% do lado REAL é foto de cachorro | **0,4667** | **Uma em cada três fotografias reais públicas é classificada como IA.** ### Por que, exatamente A ETAPA F testou e descartou, com medição: proporção, resolução, formato, compressão, capturas de tela, atalho de contêiner e perda de ordenação. O que restou foi **composição e cobertura**: * o FPR de ~10% **é propriedade do acervo, não do detector**. Em conteúdo casado, o domínio `pessoas` dá FPR **0,0051** no acervo próprio contra **0,2513** no público — 49× de diferença. O acervo próprio só parece bom porque **32% dele é retrato**; * o salto de 0,0972 para 0,4667 no External V2 é **~87% composição**: o mesmo conteúdo (fotografia real de cachorro) já dava FPR 0,4667 *dentro* do 882, onde pesava 5,95% do lado REAL; no V2 pesa 87,78%; * **cobertura é o achado acionável**: o treino tem **1 cena REAL de cachorro em 234**; validação e teste têm **zero**. ### Por domínio, no pool público Nenhum dos nove domínios é normal. Todos têm FPR entre 2,2× e 5,1× o FPR de operação, com p binomial ≤ 0,007 em todos. | domínio | n | FP | FPR | |---|---:|---:|---:| | `coco:animais` | 251 | 124 | **0,4940** | | `coco:veiculos` | 140 | 59 | 0,4214 | | `imagenet:sem_rotulo` | 930 | 354 | 0,3806 | | `coco:interiores` | 155 | 54 | 0,3484 | | `coco:natureza` | 48 | 16 | 0,3333 | | `coco:alimentos` | 123 | 34 | 0,2764 | | `coco:desconhecida` | 165 | 45 | 0,2727 | | `coco:pessoas` | 565 | 142 | 0,2513 | | `coco:predios` | 56 | 12 | **0,2143** | **Subir o threshold não conserta isso.** A ETAPA N mediu que a amplitude *relativa* de FPR entre domínios **cresce** com o limiar: 0,27 em t = 0,10; 0,81 em t = 0,48; 1,59 em t = 0,90. E levar o FPR público a 10% exige t = 0,7676 e custa **+60 falsos negativos** no External 882. ### O que continua funcionando sob deslocamento A **ordenação**. O ROC-AUC no External V2 é **0,9836** — o mais alto de todos os conjuntos. O modelo continua sabendo ordenar; o que ele não sabe é onde cortar. Se você puder usar o AIDA para *ranquear* em vez de *decidir*, use. ## Limitations 1. **Dataset shift severo.** FPR de 0,0915 a 0,4667 conforme a população. Se o seu material não se parece com o acervo de treino, **os números publicados não se aplicam a você**. Meça no seu domínio antes de confiar. 2. **Dependência de domínio no B3.** Amplitude de FPR de 0,72 entre domínios, contra 0,18 do B2 e 0,16 do B5. 3. **O ponto de operação não é ótimo em nenhuma população**, e não existe um que seja bom em todas — os limiares ótimos de três populações estão a 0,5725 de distância entre si. 4. **Falsos positivos confiantes.** 89% dos FP do pool público estão a mais de 0,05 acima do limiar, com `score_clip` mediano **0,8811**. Não são hesitações — o modelo está confiantemente errado, e nenhum ajuste de corte os alcança. 5. **Falsos negativos confiantes.** No 882, 93% dos FN estão bem abaixo do limiar, com `score_clip` mediano **0,0721**, e concentram-se no gerador `openai`, cujas cenas moram em território REAL no espaço de representação. 6. **Generalização entre geradores não é garantida.** O treino cobre OpenAI, Google Gemini e ByteDance. Geradores fora dessa lista (Midjourney, Stable Diffusion, FLUX, modelos futuros) **não foram avaliados** neste champion. 7. **Não detecta edição local.** A hipótese "foto real com edição local" nunca pôde ser testada: o repositório não possui esse grupo. 8. **Avaliação limitada.** O n efetivo é de **cenas**, não de imagens: 89 cenas na validação, 147 no 882, 150 no V2. Os intervalos de confiança são largos — o FPR do 882 é 0,0972 com IC95 [0,0437 · 0,1596] por cena. 9. **Robustez a degradação não é reavaliada aqui.** A ETAPA D.2 mediu queda sob compressão, redimensionamento e ruído; os números deste card são da condição canônica. 10. **Sem garantia forense e sem garantia de autenticidade.** O AIDA não estabelece origem, autoria, cadeia de custódia nem integridade de arquivo. 11. **O release não inclui a camada de proveniência C2PA** do sistema de laboratório — ver *Escopo do release*. ## Ethical / Safety Considerations * **O resultado do AIDA não é prova.** É uma probabilidade calibrada de que a imagem se pareça, estatisticamente, com as imagens geradas por IA que o modelo viu no treino. Não estabelece origem, autoria nem intenção. * **Não use como única evidência para acusar alguém.** Com FPR entre 9% e 47% conforme o material, uma pessoa em cada duas a onze acusadas por este detector seria acusada injustamente. Decisões com consequência exigem evidência adicional e revisão humana. * **"REAL" não significa autêntico.** Significa "não se parece com IA para este modelo". Uma imagem manipulada por meios convencionais pode passar como REAL. * **Erros não são distribuídos por igual.** O FPR varia por conteúdo, e conteúdo correlaciona com pessoas, lugares e assuntos. Aplicar o AIDA a um grupo cujo material se parece com `coco:animais` (FPR 0,494) e a outro cujo material se parece com `coco:predios` (FPR 0,214) produz **taxas de erro 2,3× diferentes entre os dois grupos**. Isso é um risco de equidade, não um detalhe técnico. * **Não foi auditado para viés demográfico.** O acervo de treino é 32% retrato e não há análise de desempenho por características demográficas. Não use em contexto que afete pessoas sem essa auditoria. * **Modelos generativos evoluem.** Um detector treinado em 2026 sobre três geradores degrada contra geradores futuros. Trate a data de treino como prazo de validade. * **Ao publicar resultados obtidos com o AIDA**, publique o threshold, a população e o FPR medido nela. Um número de acurácia sem essas três coisas não significa nada neste modelo. ## Escopo do release O release entrega **o detector cujos números estão publicados**: a fusão dos três sensores. Duas camadas do sistema de laboratório ficam de fora, e a razão é metodológica, não de conveniência: * **proveniência C2PA** — no protocolo de avaliação canônico os metadados são removidos, então essa camada é **inerte em 100% das métricas publicadas** (λ = 0 em todo o `dataset_derivado`). Publicá-la faria o release se comportar de um jeito que nenhum benchmark mediu; * **explicabilidade** (mapas de calor, patches suspeitos) — não afeta o score. Nesta distribuição pública **nenhum peso acompanha o pacote** — o que segue descreve o P0 tal como ele roda no serviço hospedado do AIDA (Space `AIDAON/aida-api`, onde os pesos estão publicados). A **guarda de fora-de-domínio** (`b3_dominio.joblib`) **entra**, porque não toca o score: só marca `INCONCLUSIVO` para imagens que não são fotográficas. Sem ela, um quadrado preto sólido receberia "REAL, confiança alta". ## Licença > **Estado de publicação.** O pacote está **tecnicamente pronto** para > publicação — equivalência, instalação limpa e testes verificados. A > **redistribuição dos pesos permanece condicionada** à resolução das questões > documentadas em [`LICENSES.md`](LICENSES.md). Enquanto elas não forem > resolvidas, os pesos **não** devem ser descritos como *open source*, > licenciados sob MIT, redistribuíveis ou de uso comercial, e a publicação **não > está juridicamente autorizada** por este documento — que não é parecer > jurídico. **O código é MIT. Os pesos não têm licença declarada.** As duas coisas são separadas e não devem ser confundidas. | componente | estado | |---|---| | código (`aida/`, `aida_p0/`, `scripts/`, documentação) | MIT — `LICENSE_CONFIRMED` | | **pesos (`models/`, 10 artefatos)** | **`LICENSE_UNKNOWN_REVIEW_REQUIRED`** | | backbone CLIP `ViT-B-32-quickgelu`/`openai` | não redistribuído — baixado pelo `open_clip` | | dependências Python | instaladas pelo `pip`, não redistribuídas | | `pillow-heif` (opcional) | GPLv2 — `LICENSE_WITH_CONDITIONS`, fora do `requirements.txt` | ### O que a auditoria de licenças resolveu Uma auditoria de proveniência (ETAPA O) cruzou o manifesto do champion com os catálogos de coleta de terceiros do repositório, por nome de cena **e** por SHA-256, com controle positivo. O resultado: **Nenhum material de terceiros treinou o P0.** As 4.475 imagens vêm apenas de `dataset/ia/` e `dataset/real/` — o acervo próprio. As faixas de numeração são disjuntas das coletas de terceiros (champion `real1..real438`; dog.ceo `real439..real538`; Wikimedia `real539..real548`), com zero interseção nos dois critérios. **Consequência:** a cláusula **não comercial** do GenImage/ImageNet (`CC-BY-NC-SA-4.0`) e a restrição a pesquisa do dog.ceo **não alcançam os pesos**, porque esse material nunca entrou no treino. Ele foi usado **apenas em avaliação**, e só números agregados aparecem neste documento. ### O que a auditoria NÃO resolveu Duas perguntas continuam abertas, e nenhuma é resolvível por engenharia: 1. **consentimento das pessoas fotografadas** — ~32% do lado REAL do acervo é retrato, e o repositório não documenta consentimento para treino ou redistribuição; 2. **termos de uso dos serviços geradores** — as imagens de IA foram geradas em OpenAI, Google Gemini e ByteDance; os termos não foram verificados documento a documento nem arquivados. `DATASET.md` classifica o acervo próprio como `UNKNOWN_REVIEW_REQUIRED` e diz que aquela triagem é "de engenharia, não parecer jurídico". Esta auditoria não tem base para mudar isso. ### Enquanto a pendência estiver aberta **Não descreva os pesos como *open source*, *redistributable*, *commercially usable*, nem como MIT/Apache/CC-BY.** O campo `license` do repositório está como `other` exatamente por isso. Detalhe completo em `LICENSES.md`. ## Reprodutibilidade O pipeline deste release foi verificado contra o pipeline oficial do laboratório: **40 imagens do `teste_externo_882`, em processos separados, com diferença máxima de exatamente `0,0` nos quatro scores**. Ver `RELEASE_BENCHMARK.md` para a tabela e para a análise do desvio de ~1e-6 observado contra o cache de 2026-08-27 (mudança de versão do PyTorch, sem efeito em nenhuma decisão). ## Citation Trabalho de conclusão de curso; **ainda sem publicação formal e sem DOI**. Enquanto não houver, cite o repositório e a versão do release: ```bibtex @software{aida_p0_2026, title = {AIDA P0 — um detector de imagens geradas por IA, com dataset shift documentado}, year = {2026}, note = {Versão do release: aida-p0-1.0.0. Threshold oficial: 0.48158617244389096. Sem DOI: trabalho de conclusão de curso não publicado formalmente.} } ``` **Não invente um DOI nem uma referência de periódico para este trabalho.**