Detecting AI-generated faces for digital literacy
Julissa Lema · Kristine Johnson · Ricky Dixon · Shloka Kandukuri
git clone https://github.com/kristinealli/SyntheticSight.git
cd SyntheticSight
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txtpython -m src.inference --image path/to/image.jpg- Data card — dataset source, preprocessing, splits, and limits
- Evaluation — metrics, threshold selection, and errors
- Bias and ethics — audit scope and responsible use
- Project history — consolidation and checkpoint audit
Synthetic Sight is a reproducible computer-vision research prototype that asks:
Can a CNN classifier distinguish real human faces from StyleGAN-generated synthetic faces well enough to help flag possible misinformation?
The final system uses ImageNet-pretrained ResNet-50 transfer learning to classify still face images as Real (0) or Synthetic/Fake (1).
Synthetic Sight is a review-support signal, not an authentication service or a universal deepfake detector.
| Metric | Final result |
|---|---|
| Locked test images | 20,000 (10,000 real / 10,000 synthetic) |
| Accuracy | 99.69% |
| Fake F1 | 99.69% |
| ROC-AUC | 99.995% |
| Decision threshold | 0.51 |
| False positives | 39 real images flagged synthetic |
| False negatives | 23 synthetic images labeled real |
For evaluation details, including class-specific metrics and the confusion
matrix, see docs/evaluation.md.
These results show extremely strong separation within this FFHQ-versus-StyleGAN benchmark. They do not establish equivalent performance for newer generators, face swaps, video, screenshots, recompressed media, edited real images, or uncontrolled real-world images.
The test split was held out while the model, checkpoint, and threshold were developed. These results show extremely strong separation within this benchmark; they do not establish the same performance on newer generators, face swaps, video, screenshots, heavy recompression, or uncontrolled real-world images.
This repository is consolidated around the final ResNet-50 pipeline used for
the presentation. See docs/project-history.md for the full audit
trail and earlier experiments.
flowchart LR
A[RGB face image] --> B[Resize 224 × 224]
B --> C[ImageNet normalization]
C --> D[ResNet-50 backbone]
D --> E[Global average pooling]
E --> F[Linear 2048 → 256]
F --> G[BatchNorm + ReLU + Dropout 0.30]
G --> H[Linear 256 → 1]
H --> I[Sigmoid synthetic score]
I --> J{score ≥ 0.51?}
J -->|Yes| K[Synthetic / Fake]
J -->|No| L[Real]
- Dataset: Kaggle 140k Real and Fake Faces — FFHQ real faces + StyleGAN synthetic faces.
- Splits used: 100,000 train, 20,000 validation, 20,000 locked test images.
- Input: RGB,
224 × 224, ImageNet normalization. - Training augmentation only: horizontal flip (
p=0.5) and light color jitter. - Stage 1: freeze the pretrained backbone and train the new classifier head for 3 epochs.
- Stage 2: unfreeze ResNet-50
layer4and fine-tune it with the head. - Loss:
BCEWithLogitsLoss. - Optimizer: Adam, weight decay
1e-4. - Learning rates: head
5e-4;layer41e-5when fine-tuning starts. - Seed: 13; batch size 32; maximum 15 epochs.
- Threshold selection: validation sweep from
0.05to0.95in0.01increments, maximizing Fake F1. - Selected model: epoch 13 at threshold
0.51.
The final notebook's implementation monitors validation Fake F1 for checkpointing. Epoch 13 also has the lowest recorded validation loss, which is why the final presentation's “lowest validation loss” description identifies the same checkpoint.
SyntheticSight/
├── README.md
├── assets/ # Final-run plots used by documentation
├── deployment/
│ ├── streamlit_app.py # Interactive research prototype
│ ├── api.py # FastAPI inference endpoint
│ └── Dockerfile
├── docs/
├── models/
├── notebooks/
├── scripts/
├── src/synthetic_sight/ # Shared model and inference code
└── tests/ # Preprocessing/model contract tests
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
python -m pip install --upgrade pip
pip install -e ".[app,api]"For notebook work:
pip install -e ".[research,dev]"The verified epoch-13 final checkpoint is included at:
models/best_resnet50.pth
Verify its architecture and metadata contract before deployment:
python scripts/verify_checkpoint.py models/best_resnet50.pthExpected SHA-256:
d9a7fd6a692c942b550f9848500dc3ffb10d5809cb0d0091990648bf369ad21c
The validator checks the final architecture contract, epoch, label mapping, and threshold. A legacy artifact fails rather than silently producing mismatched predictions.
streamlit run deployment/streamlit_app.pyuvicorn deployment.api:app --reloadInteractive API documentation is available at /docs while the service is running.
The official test set contains 10,000 real and 10,000 synthetic images and was evaluated only after development decisions were complete.
| Ground truth | Predicted Real | Predicted Synthetic |
|---|---|---|
| Real (10,000) | 9,961 TN | 39 FP |
| Synthetic (10,000) | 23 FN | 9,977 TP |
See docs/evaluation.md for metric definitions, threshold interpretation, and error analysis.
Balanced Real/Fake classes do not establish demographic fairness. The project therefore added a preliminary apparent-lightness audit using OpenCV face detection, forehead/cheek sampling, and CIE Lab L*. This is a measurable image characteristic—not race, ethnicity, gender, ancestry, or inherent skin color—and it is sensitive to lighting, exposure, editing, makeup, and face-detection errors.
The detector should flag content for review, not authenticate it. False positives can cast doubt on legitimate images; false negatives can create false reassurance. See docs/bias-and-ethics.md.
- File paths were checked for zero overlap across training, validation, and test partitions.
- The test split stayed locked until checkpoint and threshold decisions were complete.
- The final training provenance traces to the executed source notebook
training_exploration_reinteration_kristine.ipynb; the polished repository includes its consolidated counterpart asnotebooks/01_resnet50_final_training.ipynb. - The notebook records the sample configuration, labels, seed, transforms, training schedule, checkpoint metadata, and evaluation logic.
- The final repository deliberately rejects legacy checkpoints whose architecture metadata does not match the final run.
- A stronger future audit should also check image near-duplicates and source-level correlations.
- Test the existing model on unseen generator families before retraining to measure generator drift.
- Evaluate compression, resizing, screenshots, filters, and other real-world transformations.
- Join apparent-lightness audit rows to prediction/error records and compare error rates with sample sizes and uncertainty.
- Evaluate probability calibration rather than assuming model scores are literal real-world probabilities.
- Extend beyond still images with video-specific, spatiotemporal benchmarks and architectures.
- Architecture
- Dataset and data protocol
- Evaluation and metrics
- Bias and ethics
- Deployment
- Project evolution
- Repository review and consolidation decisions
- References
Core references include He et al. (2016) for ResNet, Deng et al. (2009) for ImageNet, Karras et al. (2019) for StyleGAN, Mo (2020) for the benchmark dataset, and Nightingale & Farid (2022) for the human-perception motivation. Full citations are in docs/references.md.
Use statement: Synthetic Sight is an educational research prototype. Its output is a model score under a specific benchmark distribution; it should not be treated as legal proof, identity verification, provenance certification, or an automated high-impact decision.




