--- license: mit tags: - image-classification - medical-imaging - cervical-cancer - pytorch - safetensors - cnn datasets: - custom metrics: - accuracy - f1 pipeline_tag: image-classification library_name: pytorch --- # CerviGuard - Cervical Transformation Zone Classifier ## Model Description This model classifies cervical images into 3 transformation zone types, which is important for colposcopy evaluation and cervical cancer screening. | Label | Type | Description | |-------|------|-------------| | 0 | Type 1 | Transformation zone fully visible on ectocervix | | 1 | Type 2 | Transformation zone partially visible (extends into endocervical canal) | | 2 | Type 3 | Transformation zone not visible (entirely within endocervical canal) | --- ## Model Architecture ### Overview **BaseCNN** - A simple convolutional neural network with 4 conv blocks and 2 fully connected layers. ``` ┌─────────────────────────────────────────────────────────────┐ │ INPUT (256×256×3) │ └─────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────────────────────────────────────────┐ │ CONV BLOCK 1 │ │ Conv2d(3→32, 3×3) → BatchNorm2d → ReLU → MaxPool2d(2×2) │ │ Output: 128×128×32 │ └─────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────────────────────────────────────────┐ │ CONV BLOCK 2 │ │ Conv2d(32→64, 3×3) → BatchNorm2d → ReLU → MaxPool2d(2×2) │ │ Output: 64×64×64 │ └─────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────────────────────────────────────────┐ │ CONV BLOCK 3 │ │ Conv2d(64→128, 3×3) → BatchNorm2d → ReLU → MaxPool2d(2×2) │ │ Output: 32×32×128 │ └─────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────────────────────────────────────────┐ │ CONV BLOCK 4 │ │ Conv2d(128→256, 3×3) → BatchNorm2d → ReLU → MaxPool2d(2×2)│ │ Output: 16×16×256 │ └─────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────────────────────────────────────────┐ │ GLOBAL POOLING │ │ AdaptiveAvgPool2d(1×1) │ │ Output: 1×1×256 → Flatten → 256 │ └─────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────────────────────────────────────────┐ │ FC BLOCK 1 │ │ Linear(256→256) → ReLU → Dropout(0.4) │ └─────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────────────────────────────────────────┐ │ FC BLOCK 2 │ │ Linear(256→128) → ReLU → Dropout(0.4) │ └─────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────────────────────────────────────────┐ │ CLASSIFIER │ │ Linear(128→3) │ └─────────────────────────────────────────────────────────────┘ │ ┌─────────────────────────────────────────────────────────────┐ │ OUTPUT (3 logits) │ │ [Type 1, Type 2, Type 3] │ └─────────────────────────────────────────────────────────────┘ ``` ### Layer Details | Layer | Type | In Channels | Out Channels | Kernel | Output Size | |-------|------|-------------|--------------|--------|-------------| | conv_layers.0 | Conv2d | 3 | 32 | 3×3 | 256×256×32 | | conv_layers.1 | BatchNorm2d | 32 | 32 | - | 256×256×32 | | conv_layers.2 | ReLU | - | - | - | 256×256×32 | | conv_layers.3 | MaxPool2d | - | - | 2×2 | 128×128×32 | | conv_layers.4 | Conv2d | 32 | 64 | 3×3 | 128×128×64 | | conv_layers.5 | BatchNorm2d | 64 | 64 | - | 128×128×64 | | conv_layers.6 | ReLU | - | - | - | 128×128×64 | | conv_layers.7 | MaxPool2d | - | - | 2×2 | 64×64×64 | | conv_layers.8 | Conv2d | 64 | 128 | 3×3 | 64×64×128 | | conv_layers.9 | BatchNorm2d | 128 | 128 | - | 64×64×128 | | conv_layers.10 | ReLU | - | - | - | 64×64×128 | | conv_layers.11 | MaxPool2d | - | - | 2×2 | 32×32×128 | | conv_layers.12 | Conv2d | 128 | 256 | 3×3 | 32×32×256 | | conv_layers.13 | BatchNorm2d | 256 | 256 | - | 32×32×256 | | conv_layers.14 | ReLU | - | - | - | 32×32×256 | | conv_layers.15 | MaxPool2d | - | - | 2×2 | 16×16×256 | | adaptive_pool | AdaptiveAvgPool2d | - | - | - | 1×1×256 | | fc_layers.0 | Linear | 256 | 256 | - | 256 | | fc_layers.1 | ReLU | - | - | - | 256 | | fc_layers.2 | Dropout | - | - | p=0.4 | 256 | | fc_layers.3 | Linear | 256 | 128 | - | 128 | | fc_layers.4 | ReLU | - | - | - | 128 | | fc_layers.5 | Dropout | - | - | p=0.4 | 128 | | classifier | Linear | 128 | 3 | - | 3 | ### Model Summary | Property | Value | |----------|-------| | **Total Parameters** | 488,451 | | **Trainable Parameters** | 488,451 | | **Input Size** | (B, 3, 256, 256) | | **Output Size** | (B, 3) | | **Model Size** | ~1.9 MB | --- ## Training Configuration | Parameter | Value | |-----------|-------| | Learning Rate | 1e-4 | | Batch Size | 32 | | Dropout | 0.4 | | Optimizer | Adam | | Loss Function | CrossEntropyLoss | | Epochs | 50 | | Best Epoch | 41 | --- ## Performance | Metric | Value | |--------|-------| | **Validation Accuracy** | 61.69% | | **Macro F1 Score** | 61.81% | ### Per-Class Performance | Type | Precision | Recall | F1 Score | |------|-----------|--------|----------| | Type 1 | - | - | 68.32% | | Type 2 | - | - | 56.41% | | Type 3 | - | - | 60.69% | --- ## Usage ### Installation ```bash pip install torch torchvision safetensors huggingface_hub ``` ### Quick Start (Local) ```python import torch from PIL import Image from torchvision import transforms # Load model from model import BaseCNN model = BaseCNN.from_pretrained("./") model.eval() # Preprocess image transform = transforms.Compose([ transforms.Resize((256, 256)), transforms.ToTensor(), ]) image = Image.open("cervical_image.jpg").convert("RGB") input_tensor = transform(image).unsqueeze(0) # Inference with torch.no_grad(): output = model(input_tensor) probabilities = torch.softmax(output, dim=1) prediction = output.argmax(dim=1).item() labels = ["Type 1", "Type 2", "Type 3"] print(f"Prediction: {labels[prediction]}") print(f"Confidence: {probabilities[0][prediction]:.2%}") ``` ### Load from Hugging Face Hub ```python from huggingface_hub import hf_hub_download from safetensors.torch import load_file import torch import json import importlib.util # Download files repo_id = "toderian/cerviguard_transfer_zones" model_weights = hf_hub_download(repo_id, "model.safetensors") config_file = hf_hub_download(repo_id, "config.json") model_file = hf_hub_download(repo_id, "model.py") # Load model class dynamically spec = importlib.util.spec_from_file_location("model", model_file) model_module = importlib.util.module_from_spec(spec) spec.loader.exec_module(model_module) # Load config and create model with open(config_file) as f: config = json.load(f) model = model_module.BaseCNN(**config['model_config']) model.load_state_dict(load_file(model_weights)) model.eval() # Now use model for inference ``` --- ## Files in This Repository | File | Description | |------|-------------| | `model.safetensors` | Model weights (SafeTensors format, recommended) | | `pytorch_model.bin` | Model weights (PyTorch format, backup) | | `config.json` | Model architecture configuration | | `model.py` | Model class definition (BaseCNN) | | `preprocessor_config.json` | Image preprocessing configuration | | `README.md` | This model card | --- ## Limitations - Model was trained on a specific dataset and may not generalize to all cervical imaging equipment - Type 2 classification has lower accuracy (56.41% F1) as it represents an intermediate state - Input images should be 256×256 RGB - This is a custom PyTorch model, not compatible with `transformers.AutoModel` --- ## Citation ```bibtex @misc{cerviguard-transfer-zones, title={CerviGuard Cervical Transformation Zone Classifier}, author={toderian}, year={2026}, howpublished={\url{https://huggingface.co/toderian/cerviguard_transfer_zones}} } ``` --- ## License MIT License