Binary classifier distinguishing real portrait photos from AI-generated faces.
Fine-tunes a pre-trained ViT-B/16 using LoRA adapters (PEFT), keeping 99%+ of
the backbone frozen while adapting only the attention projections. LoRA adapters
are merged before export — no PEFT dependency at inference time.
Primary dataset: 140K Real and Fake Faces —
140 000 images, perfectly balanced, predefined train/valid/test split. Real faces from Flickr,
fake faces generated with StyleGAN2.
1import numpy as np
2import onnxruntime as ort
3from PIL import Image
4from torchvision.transforms import CenterCrop, Compose, Normalize, Resize, ToTensor
5
6transform = Compose([
7 Resize(256),
8 CenterCrop(224),
9 ToTensor(),
10 Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
11])
12
13session = ort.InferenceSession("model_quint8.onnx")
14
15img = Image.open("face.jpg").convert("RGB")
16x = transform(img).unsqueeze(0).numpy()
17logit = session.run(None, {"input": x})[0][0, 0]
18prob_fake = float(1 / (1 + np.exp(-logit)))
19print(f"Fake probability: {prob_fake:.3f}")
The model converges rapidly — 96.8% accuracy is already reached after epoch 2, with diminishing
gains thereafter. LoRA keeps 99%+ of backbone parameters frozen throughout, training only
~0.68% of total parameters (590k adapter params on top of 86M ViT-B/16 backbone).
Dynamic INT8 quantization reduces model size by 4× and latency by 3× with a negligible
0.16 percentage point accuracy drop.