13 206 4

OnlyFans Content Identify

Como implementei um protótipo experimental ONNX para classificação de imagens com Transformers.js.

Ilustração de um modelo de aprendizado de máquina

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

ArquivoEvidência que ele forneceO que ele não me permite concluir
README.mdCard “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
.gitattributesRastreia .onnx e muitos formatos binários com Git LFSQualquer propriedade científica do modelo
config.jsonArquitetura ViTForImageClassification, hiperparâmetros estruturais e mapa de duas classesCheckpoint-base, inicialização, treinamento ou qualidade
preprocessor_config.jsonRedimensionamento, reescala e normalização esperadosPré-processamento aplicado ao corpus de treino
quantize_config.jsonEstratégia por canal, faixa reduzida, operadores vistos e pesos QUInt8Versão exata da ferramenta ou perda de qualidade causada pela quantização
onnx/model.onnxGrafo e pesos em ponto flutuante, entrada pixel_values e saída logitsModelo-fonte reproduzível ou métricas de equivalência
onnx/model_quantized.onnxVariante de quantização dinâmica com operações inteirasAceleraçã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 z0,z1z_0,z_1, a probabilidade apresentada pela pipeline para a classe adult é:

padult=ez1ez0+ez1.p_{adult}=\frac{e^{z_1}}{e^{z_0}+e^{z_1}}.

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 1/2551/255 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 xx entre 0 e 255:

x=x/2550,50,5=2x2551.x'=\frac{x/255-0{,}5}{0{,}5}=\frac{2x}{255}-1.

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.2
import { 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 tt sobre padultp_{adult}, reporte matriz de confusão, precisão, revocação, especificidade e F1:

PPV=TPTP+FP,TPR=TPTP+FN,FPR=FPFP+TN.\mathrm{PPV}=\frac{TP}{TP+FP},\qquad \mathrm{TPR}=\frac{TP}{TP+FN},\qquad \mathrm{FPR}=\frac{FP}{FP+TN}.

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 CFPC_{FP} e CFNC_{FN}, escolha tt somente na validação, minimizando uma função declarada, por exemplo:

R(t)=CFPFP(t)+CFNFN(t),R(t)=C_{FP}FP(t)+C_{FN}FN(t),

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 tbaixot_{baixo}, não sinalizar; acima de taltot_{alto}, 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

  1. Dosovitskiy, A. et al. An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale. ICLR, 2021. arXiv.
  2. Domingues, M. onlyfans-content-identify. Hugging Face, publicado em 14 de abril de 2024. Modelo.
  3. Hugging Face. Vision Transformer (ViT). Documentação do Transformers. Documentação.
  4. Hugging Face. Transformers.js 2.17.2: pipeline, uso customizado e conversor. Pipeline; conversor; pipeline de imagem.
  5. Hugging Face. Export a model to ONNX with Optimum. Documentação.
  6. ONNX Runtime. Quantize ONNX models. Documentação.
  7. ONNX Runtime. Web application development flow. Documentação.
  8. Guo, C. et al. On Calibration of Modern Neural Networks. ICML, 2017. PMLR.
  9. 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.
  10. 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}
}