OnlyFans Content Identify: protótipo experimental de um classificador ViT em ONNX
Eu implementei o dominguesm/onlyfans-content-identify como um protótipo experimental de classificação binária de imagens, publicado no Hugging Face em 14 de abril de 2024 e marcado como image-classification, transformers.js, onnx e vit [2]. O nome sugere um domínio, mas não define a tarefa científica. No repositório, publiquei classes chamadas regular e adult; não publiquei exemplos rotulados, definição operacional de “adulto”, dados de treinamento, métricas nem protocolo de avaliação.
Publiquei sete arquivos em 14 de abril de 2024. Eles permitem executar a classificação e identificar a arquitetura exportada, mas eu não medi acurácia, cobertura nem capacidade de reconhecer plataforma, idade ou consentimento. Por isso, limito as afirmações aos comportamentos que implementei e às propriedades técnicas dos grafos.
O que implementei e publiquei
| Arquivo | Evidência que ele fornece | O que ele não me permite concluir |
|---|---|---|
README.md | Card “WIP”, licença declarada CC BY 4.0, tarefa e biblioteca; recomenda Optimum e pesos em onnx/ | Dados, treino, validação ou comando de exportação |
.gitattributes | Rastreia .onnx e muitos formatos binários com Git LFS | Qualquer propriedade científica do modelo |
config.json | Arquitetura ViTForImageClassification, hiperparâmetros estruturais e mapa de duas classes | Checkpoint-base, inicialização, treinamento ou qualidade |
preprocessor_config.json | Redimensionamento, reescala e normalização esperados | Pré-processamento aplicado ao corpus de treino |
quantize_config.json | Estratégia por canal, faixa reduzida, operadores vistos e pesos QUInt8 | Versão exata da ferramenta ou perda de qualidade causada pela quantização |
onnx/model.onnx | Grafo e pesos em ponto flutuante, entrada pixel_values e saída logits | Modelo-fonte reproduzível ou métricas de equivalência |
onnx/model_quantized.onnx | Variante de quantização dinâmica com operações inteiras | Aceleração em todo hardware ou paridade preditiva |
O campo _name_or_path vale apenas ./onlyfans-content-identify, um caminho local, e eu não registrei um checkpoint de origem no repositório [2]. Assim, com os materiais que preservei, não consigo estabelecer a linhagem dos pesos. A geometria é igual à configuração padrão de um ViT Base patch-16 de 224 pixels, mas isso não me permite concluir que os pesos vieram de google/vit-base-patch16-224, de sua variante ImageNet-21k ou de qualquer outro checkpoint [1][3]. Pesos semelhantes em forma não são prova de linhagem.
Também não publiquei pesos PyTorch, script, training_args, logs, dataset card ou hashes de imagens. Os rótulos e as tags onlyfans e twitter não identificam a origem das imagens que usei. Licença do repositório e direitos sobre o corpus de treinamento são questões diferentes.
Arquitetura e classes
O config.json especifica ViTForImageClassification: 12 blocos Transformer, dimensão oculta 768, 12 cabeças de atenção de 64 dimensões, MLP intermediário de 3.072 unidades, GELU, vieses em Q/K/V e dropout zero. A imagem nominal tem três canais e 224 × 224 pixels; cada patch mede 16 × 16. Portanto, a grade produz 14 × 14 = 196 patches. Somado o token de classificação [CLS], o encoder processa 197 tokens. A cabeça final é uma projeção linear de 768 para dois logits [1][3].
Renderizando diagrama...
O mapa é 0 → regular e 1 → adult, com problem_type = single_label_classification. Os grafos não incorporam Softmax depois da cabeça; suas 12 operações Softmax pertencem às atenções internas. Para logits finais , a probabilidade apresentada pela pipeline para a classe adult é:
Esse valor é uma normalização relativa entre dois escores, não uma probabilidade automaticamente calibrada. “Adult” tampouco é uma taxonomia suficiente: não registrei se o rótulo significa nudez, ato sexual explícito, roupa íntima, conteúdo sugestivo ou associação comercial. “Regular” é igualmente indefinido. A saída classifica a imagem inteira; não localiza regiões, pessoas ou objetos.
Pré-processamento reproduzível
O preprocessor_config.json ativa redimensionamento direto para 224 × 224 com resample = 2, reescala por e normalização RGB com média e desvio padrão iguais a 0,5. Na implementação do Transformers.js 2.17.2, o valor 2 corresponde à interpolação bilinear, a imagem é convertida para RGB por padrão e os dados passam de HWC para CHW antes de formar o lote NCHW [4]. Para um canal com intensidade entre 0 e 255:
Não há do_center_crop, preservação de proporção ou preenchimento no arquivo. Logo, a pipeline 2.x redimensiona para o quadrado, podendo deformar imagens retangulares. Reimplementar somente “resize 224” e esquecer RGB, ordem dos canais, reescala ou normalização muda a entrada do modelo.
Embora o ONNX declare altura e largura simbólicas, as posições aprendidas têm comprimento 197 e a configuração exige 224. Isso não deve ser interpretado como suporte validado a resolução arbitrária: outras formas podem falhar na soma posicional ou produzir comportamento não testado. A entrada segura é float32 com forma [lote, 3, 224, 224].
O que os grafos ONNX revelam
O grafo principal tem 343.463.896 bytes. Seus metadados registram ONNX IR 6, opset 11, produtor pytorch 2.2.1, nome main_graph e nenhum par chave-valor adicional. Há uma entrada pixel_values FLOAT, com dimensões simbólicas [batch_size, num_channels, height, width], e uma saída logits FLOAT de [batch_size, 2].
São 1.242 nós, 200 inicializadores FLOAT e 85.800.194 elementos armazenados. A estrutura inclui uma convolução para patches, 96 MatMul, 12 Softmax, 50 ReduceMean, 25 Sqrt, 12 Erf e um Gemm final. Os nomes internos percorrem vit.encoder.layer.0 até as camadas posteriores, terminando em normalização, seleção do [CLS] e classifier/Gemm. Isso confirma a implementação ViT e a cabeça binária descritas pela configuração.
O grafo quantizado tem 87.481.955 bytes, redução de aproximadamente 74,5% no arquivo. Preserva entrada e saída FLOAT, IR 6 e opset 11, mas registra produtor onnx.quantize 0.1.0 e metadado onnx.infer = onnxruntime.quant. Seus 1.517 nós incluem 50 DynamicQuantizeLinear, 73 MatMulInteger e um ConvInteger; os 349 inicializadores se dividem em 200 FLOAT, 148 UINT8 e um INT64.
Isso permite caracterizar a transformação como quantização dinâmica de pesos e ativações selecionadas, não inferência inteira ponta a ponta. O quantize_config.json define per_channel = true, reduce_range = true e weight_type = QUInt8. A documentação do ONNX Runtime explica que reduce_range reduz pesos a 7 bits e que a quantização dinâmica calcula escala e ponto zero das ativações durante a inferência [6]. Camadas de normalização, vieses e várias operações continuam em ponto flutuante.
Empacotei o modelo com a lógica usada pelo Transformers.js 2.17.2: quantize_dynamic, quantização por canal, faixa reduzida e QUInt8 na presença de Conv, por compatibilidade com o ONNX Runtime Web da época [4]. O grafo registra PyTorch 2.2.1 como produtor, e salvei a configuração com transformers_version = 4.33.2. Na publicação inicial, não registrei a versão do Optimum, a versão do ONNX Runtime, o comando, as flags, a tolerância nem o relatório de validação. Por isso, não apresento hoje uma combinação exata dessas versões como receita histórica [5].
Renderizando diagrama...
Inferência no navegador, com contrato histórico
Empacotei o repositório segundo o contrato do Transformers.js 2.x. Nessa versão, quantized: true procura literalmente onnx/model_quantized.onnx; a pipeline carrega também configuração e processador, executa o grafo via ONNX Runtime, aplica Softmax e ordena as classes [4]. Um ensaio mínimo, não uma implantação de moderação, pode ser feito assim:
npm install @xenova/transformers@2.17.2import { pipeline } from "@xenova/transformers";
const MODEL = "dominguesm/onlyfans-content-identify";
const classify = await pipeline("image-classification", MODEL, {
revision: "main",
quantized: true,
});
// Use uma imagem de teste autorizada e servida pela própria aplicação.
const scores = await classify("/fixtures/imagem-consentida.jpg", { topk: 2 });
console.table(scores);
await classify.dispose();A branch main pode avançar; para uma avaliação controlada, espelhe o artefato aprovado, registre sua data e verifique sua integridade antes do uso. O primeiro carregamento baixa cerca de 87,5 MB, além do runtime; cache, RAM de pico, latência e aquecimento devem ser medidos em aparelhos reais. A documentação atual do Transformers.js v3 substituiu quantized por dtype e usa variantes com outra convenção de nomes [4]. Não publiquei model_q8.onnx neste repositório; portanto, migrar o exemplo para @huggingface/transformers e dtype: "q8" sem reempacotar e testar não é uma conclusão sustentada pelos artefatos.
ONNX Runtime Web oferece WASM e, conforme navegador e operadores, WebGPU ou WebNN; WASM tem a cobertura de operadores mais ampla [7]. A presença de ONNX compatível torna inferência no navegador tecnicamente possível, mas não publiquei matriz de navegadores, testes end-to-end, orçamento de memória ou benchmark. Inferência local reduz o envio da imagem a um servidor, mas não elimina telemetria, requisições da própria página, cache compartilhado ou exposição ao host de uma URL remota. Imagens locais, política de rede restritiva e ausência de logs são escolhas adicionais.
Dados, métricas e validações necessários
Antes de escolher qualquer limiar, é preciso escrever uma política de anotação que defina as duas classes, casos limítrofes e unidade de decisão. Um conjunto autorizado e independente deve ser dividido por pessoa, conta ou origem, e não apenas por arquivo, para impedir que quase duplicatas apareçam em treino e teste. Deduplicação perceptual, corte temporal e estratos por fonte, composição visual, iluminação, tom de pele e apresentação de gênero ajudam a revelar atalhos e mudança de domínio. Os anotadores precisam de treinamento, concordância interavaliadores, opção de recusa e proteção psicológica.
Para um limiar sobre , reporte matriz de confusão, precisão, revocação, especificidade e F1:
Trace ROC e curva precisão-revocação em todos os limiares. ROC-AUC mede ordenação, mas pode parecer favorável quando a classe positiva é rara; PR-AUC e precisão no nível de revocação operacional são mais informativas nesse cenário [9]. Se custos de falso positivo e falso negativo forem e , escolha somente na validação, minimizando uma função declarada, por exemplo:
e avalie uma única vez no teste bloqueado. Use intervalos de confiança por bootstrap agrupado pela origem. Publique resultados por subgrupo e interseções, sem reduzir pessoas a atributos inferidos automaticamente.
Calibração exige diagrama de confiabilidade, Brier score, log-loss e ECE. Ajuste de temperatura deve usar apenas validação [8]. Repita tudo para FP32 e quantizado: compare métricas, diferença de logits, erro absoluto de probabilidades e taxa de discordância de classe. Um desenho mais seguro emprega dois limites: abaixo de , não sinalizar; acima de , encaminhar; entre ambos, abster-se. Nenhum dos limites deve causar remoção automática sem revisão e recurso.
Privacidade, moderação, idade e consentimento
Uma classificação visual adult não estabelece idade, maioridade, consentimento, legalidade, autoria, identidade, profissão ou plataforma de origem. Idade e consentimento são propriedades de pessoas e contexto, não pixels recuperáveis de modo confiável por esta cabeça binária. O modelo também não distingue conteúdo consensual de abuso, exploração, material íntimo não consentido ou material de abuso sexual infantil. Esses casos exigem processos especializados, pessoal treinado e obrigações legais específicas; não se deve montar um corpus improvisado para “testá-los”.
Falsos positivos podem censurar educação sexual, amamentação, arte, saúde ou corpos não normativos, além de suspender contas e renda. Falsos negativos podem expor usuários e revisores a conteúdo indesejado. Como não publiquei a composição do treinamento, esta versão não permite medir vieses de fonte, tom de pele, gênero e enquadramento. Recortes, compressão, texto sobreposto e ataques adversariais também precisam fazer parte de uma avaliação futura.
Imagens íntimas podem revelar vida sexual, biometria e outros dados sensíveis. Mesmo no dispositivo, aplique minimização, finalidade explícita, retenção curta, criptografia, controle de acesso, validação e base jurídica compatível com a jurisdição. Revisores humanos precisam de filas limitadas, avisos, pausas, suporte e possibilidade de recurso para as pessoas afetadas. A licença CC BY 4.0 exige atribuição para o material coberto, mas não concede consentimento dos retratados nem direitos sobre dados de treino desconhecidos [10].
Estado atual do protótipo e próximos passos
O protótipo que implementei e publiquei contém um ViT Base-like de 85,8 milhões de elementos, duas classes, pré-processamento 224 × 224, um grafo FP32 e uma variante dinâmica QUInt8 compatível com o contrato do Transformers.js 2.x. Não é possível estabelecer corpus, proveniência das imagens, política de rótulos, checkpoint-base, método de ajuste, desempenho, calibração, equidade, segurança ou compatibilidade operacional ampla.
Mantenho esta versão como experimental porque não publiquei dados, métricas nem uma validação responsável. Por isso, não a recomendo para produção, moderação automática, verificação etária, inferência de consentimento ou decisão sobre contas e pessoas.
Referências
- Dosovitskiy, A. et al. An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale. ICLR, 2021. arXiv.
- Domingues, M. onlyfans-content-identify. Hugging Face, publicado em 14 de abril de 2024. Modelo.
- Hugging Face. Vision Transformer (ViT). Documentação do Transformers. Documentação.
- Hugging Face. Transformers.js 2.17.2: pipeline, uso customizado e conversor. Pipeline; conversor; pipeline de imagem.
- Hugging Face. Export a model to ONNX with Optimum. Documentação.
- ONNX Runtime. Quantize ONNX models. Documentação.
- ONNX Runtime. Web application development flow. Documentação.
- Guo, C. et al. On Calibration of Modern Neural Networks. ICML, 2017. PMLR.
- Saito, T.; Rehmsmeier, M. The Precision-Recall Plot Is More Informative than the ROC Plot When Evaluating Binary Classifiers on Imbalanced Datasets. PLOS ONE, 2015. DOI.
- Creative Commons. Attribution 4.0 International. Licença.
BibTeX
@inproceedings{dosovitskiy2021vit,
title = {An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale},
author = {Dosovitskiy, Alexey and others},
booktitle = {International Conference on Learning Representations},
year = {2021},
url = {https://arxiv.org/abs/2010.11929}
}
@misc{domingues2024onlyfans,
title = {onlyfans-content-identify},
author = {Domingues, Maicon},
year = {2024},
howpublished = {Hugging Face model repository},
note = {Published 14 April 2024},
url = {https://huggingface.co/dominguesm/onlyfans-content-identify}
}
@software{transformersjs2024,
title = {Transformers.js},
author = {{Hugging Face}},
version = {2.17.2},
year = {2024},
url = {https://github.com/huggingface/transformers.js/tree/2.17.2}
}
@software{optimumonnx,
title = {Hugging Face Optimum: ONNX Exporters},
author = {{Hugging Face}},
url = {https://huggingface.co/docs/optimum/en/exporters/onnx/usage_guides/export_a_model}
}
@software{onnxruntime,
title = {ONNX Runtime},
author = {{Microsoft}},
url = {https://onnxruntime.ai/}
}
@inproceedings{guo2017calibration,
title = {On Calibration of Modern Neural Networks},
author = {Guo, Chuan and Pleiss, Geoff and Sun, Yu and Weinberger, Kilian Q.},
booktitle = {Proceedings of the 34th International Conference on Machine Learning},
pages = {1321--1330},
year = {2017},
url = {https://proceedings.mlr.press/v70/guo17a.html}
}
@article{saito2015precisionrecall,
title = {The Precision-Recall Plot Is More Informative than the ROC Plot When Evaluating Binary Classifiers on Imbalanced Datasets},
author = {Saito, Takaya and Rehmsmeier, Marc},
journal = {PLOS ONE},
volume = {10},
number = {3},
pages = {e0118432},
year = {2015},
doi = {10.1371/journal.pone.0118432}
}