This repository contains a minimal feasibility pipeline for:
- frozen CLIP image encoder (
openai/clip-vit-base-patch32) - embedding extraction
- logistic regression linear probe
- binary task:
exit-site presentvsexit-site absent/random
The goal is to test whether there is usable signal before investing in heavier model training.
- Task: reject random or non-exit-site photos while keeping exit-site photos.
- Positive class: exit-site visible (
label=1). - Negative class: non-exit-site (
label=0) with three negative groups:- hard: skin redness/wound/scar but not exit-site
- medium: normal abdominal skin
- easy: non-medical images
Go/no-go criterion:
- If recall (positive class) is
>= 0.8: signal is likely learnable; proceed to stronger models (fine-tuned CNN or detection model). - If recall is
< 0.8: refine dataset definition and negative sampling first; do not switch model family yet.
Expected working directories:
data/positive/data/negative/hard/data/negative/medium/data/negative/easy/
The preparation script will generate:
data/manifest.csvdata/summary.json
Primary positive source (local):
../ntuh-pd-exit-site-classification/dataset
Suggested public sources for negatives (manual download + local unpack):
- hard negatives:
- CO2Wounds-V2
- WoundsDB
- ISIC public collections
- medium negatives:
- Abdominal Skin Segmentation Dataset (Apache-2.0)
- easy negatives:
- CIFAR-10 (auto-downloaded by script through torchvision)
Always verify license terms for each downloaded dataset and keep citation/attribution records.
python3 -m venv .venv
source .venv/bin/activate
pip install -U pip
pip install -r requirements.txtYou can build any size >=100. For fast feasibility, start with 200.
For stronger stability, use an expanded set (for example 480).
Example:
python scripts/prepare_mvp_dataset.py \
--positive-source ../ntuh-pd-exit-site-classification/dataset \
--hard-source /path/to/hard_negatives \
--medium-source /path/to/medium_negatives \
--target-total 480 \
--positive-ratio 0.45 \
--easy-ratio 0.08 \
--hard-ratio 0.75 \
--seed 42Notes:
- Easy negatives are downloaded from CIFAR-10 by default.
- If hard/medium paths are missing, the script still runs but prints shortages.
python scripts/run_clip_linear_probe.py \
--manifest data/manifest.csv \
--test-size 0.2 \
--seed 42 \
--augment-copies 2 \
--augment-noise-std 0.01To visualize training accuracy in Weights & Biases (W&B), use SGD probe mode:
python scripts/run_clip_linear_probe.py \
--manifest data/manifest.csv \
--probe-trainer sgd \
--probe-epochs 40 \
--wandb-enable \
--wandb-project ntuh-exit-site-clip-probe \
--wandb-run-name expanded-aug-seed42For local testing without uploading to W&B cloud, set:
--wandb-mode offlineThe script can save a deployable bundle and upload it directly.
python scripts/run_clip_linear_probe.py \
--manifest data/manifest.csv \
--test-size 0.2 \
--seed 42 \
--augment-copies 2 \
--augment-noise-std 0.01 \
--model-bundle-dir outputs/model_bundle \
--hf-repo-id ruby0322/pd-exit-site-clip-linear-probeRequired auth for upload:
hf auth loginbeforehand, or- set
HF_TOKENin environment.
Uploaded bundle files:
linear_probe.joblibbundle_config.jsonREADME.md
The run script writes artifacts to outputs/:
outputs/metrics.jsonoutputs/confusion_matrix.pngoutputs/predictions.csvoutputs/errors_false_negative.csvoutputs/errors_hard_negative_fp.csvoutputs/embedding_cache.npzoutputs/train_curve.csv(epoch-leveltrain_acc/test_acc)outputs/model_bundle/(deployable probe bundle)
Focus on:
- false negatives (
label=1,pred=0) - hard negative failures (
neg_group=hard,label=0,pred=1)
With target-total=480, augment-copies=2, augment-noise-std=0.01, seed 42:
accuracy = 0.9895833333333334recall_positive = 1.0false_negative_count = 0hard_negative_failure_count = 1
As of this update, the 98.9% model is approved as the current production pre-screen baseline.
- Production model repo:
ruby0322/pd-exit-site-clip-linear-probe
- Production URL:
https://huggingface.co/ruby0322/pd-exit-site-clip-linear-probe
- Decision basis:
accuracy = 0.9895833333333334recall_positive = 1.0false_negative_count = 0
Deployment note:
- Pin
PRESCREEN_MODEL_REVISIONin backend config for reproducibility.