Phase 3 classifier
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"pretrained": true,
|
||||||
|
"epochs": 15,
|
||||||
|
"image_size": 224,
|
||||||
|
"subsample": 0.2,
|
||||||
|
"augment": false,
|
||||||
|
"data_dir": "cropped/classifier"
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"extends": "p3_base.json",
|
||||||
|
"run_name": "p3_convnext_tiny",
|
||||||
|
"backbone": "convnext_tiny"
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"extends": "p3_base.json",
|
||||||
|
"run_name": "p3_efficientnet_b0",
|
||||||
|
"backbone": "efficientnet_b0"
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"extends": "p3_base.json",
|
||||||
|
"run_name": "p3_mobilenetv3_small",
|
||||||
|
"backbone": "mobilenet_v3_small"
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"extends": "p3_base.json",
|
||||||
|
"run_name": "p3_resnet34",
|
||||||
|
"backbone": "resnet34"
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"extends": "p3_base.json",
|
||||||
|
"run_name": "p3_resnet50",
|
||||||
|
"backbone": "resnet50"
|
||||||
|
}
|
||||||
@@ -30,6 +30,6 @@ def load_checkpoint(model: nn.Module, path: Union[Path, str], device) -> nn.Modu
|
|||||||
|
|
||||||
|
|
||||||
# Importing the modules triggers their register() calls
|
# Importing the modules triggers their register() calls
|
||||||
from src.models import simple_cnn, resnet, efficientnet # noqa: E402, F401
|
from src.models import simple_cnn, resnet, efficientnet, mobilenet, convnext # noqa: E402, F401
|
||||||
|
|
||||||
__all__ = ["get_model", "load_checkpoint", "register"]
|
__all__ = ["get_model", "load_checkpoint", "register"]
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import torch.nn as nn
|
||||||
|
from torchvision import models
|
||||||
|
|
||||||
|
from src.models import register
|
||||||
|
|
||||||
|
|
||||||
|
# ConvNeXt's classification head is a Sequential ending in (LayerNorm2d, Flatten, Linear); [-1] targets the Linear
|
||||||
|
def build(cfg: dict) -> nn.Module:
|
||||||
|
backbone = cfg.get("backbone", "convnext_tiny")
|
||||||
|
pretrained = cfg.get("pretrained", True)
|
||||||
|
|
||||||
|
if backbone == "convnext_tiny":
|
||||||
|
weights = models.ConvNeXt_Tiny_Weights.DEFAULT if pretrained else None
|
||||||
|
model = models.convnext_tiny(weights=weights)
|
||||||
|
elif backbone == "convnext_small":
|
||||||
|
weights = models.ConvNeXt_Small_Weights.DEFAULT if pretrained else None
|
||||||
|
model = models.convnext_small(weights=weights)
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unsupported ConvNeXt backbone: {backbone!r}. Supported: convnext_tiny, convnext_small")
|
||||||
|
|
||||||
|
in_features = model.classifier[-1].in_features
|
||||||
|
model.classifier[-1] = nn.Linear(in_features, 1)
|
||||||
|
return model
|
||||||
|
|
||||||
|
|
||||||
|
register("convnext_tiny", build)
|
||||||
|
register("convnext_small", build)
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import torch.nn as nn
|
||||||
|
from torchvision import models
|
||||||
|
|
||||||
|
from src.models import register
|
||||||
|
|
||||||
|
|
||||||
|
# MobileNetV3's classification head is a Sequential; [-1] targets the final Linear
|
||||||
|
def build(cfg: dict) -> nn.Module:
|
||||||
|
backbone = cfg.get("backbone", "mobilenet_v3_small")
|
||||||
|
pretrained = cfg.get("pretrained", True)
|
||||||
|
|
||||||
|
if backbone == "mobilenet_v3_small":
|
||||||
|
weights = models.MobileNet_V3_Small_Weights.DEFAULT if pretrained else None
|
||||||
|
model = models.mobilenet_v3_small(weights=weights)
|
||||||
|
elif backbone == "mobilenet_v3_large":
|
||||||
|
weights = models.MobileNet_V3_Large_Weights.DEFAULT if pretrained else None
|
||||||
|
model = models.mobilenet_v3_large(weights=weights)
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unsupported MobileNet backbone: {backbone!r}. Supported: mobilenet_v3_small, mobilenet_v3_large")
|
||||||
|
|
||||||
|
in_features = model.classifier[-1].in_features
|
||||||
|
model.classifier[-1] = nn.Linear(in_features, 1)
|
||||||
|
return model
|
||||||
|
|
||||||
|
|
||||||
|
register("mobilenet_v3_small", build)
|
||||||
|
register("mobilenet_v3_large", build)
|
||||||
+23
-28
@@ -328,7 +328,7 @@ Note: Comparison pairs (baseline vs treatment) are defined in the analysis noteb
|
|||||||
### 3.1 Experiment Configs
|
### 3.1 Experiment Configs
|
||||||
Use the best preprocessing choices from Phase 2. The placeholders below assume 224×224, face crop enabled, and no augmentation unless Phase 2 results justify different settings.
|
Use the best preprocessing choices from Phase 2. The placeholders below assume 224×224, face crop enabled, and no augmentation unless Phase 2 results justify different settings.
|
||||||
|
|
||||||
- [ ] Create `classifier/configs/phase3/p3_resnet34.json`
|
- [x] Create `classifier/configs/phase3/p3_resnet34.json`
|
||||||
- backbone: resnet34
|
- backbone: resnet34
|
||||||
- pretrained: true
|
- pretrained: true
|
||||||
- epochs: 15
|
- epochs: 15
|
||||||
@@ -336,14 +336,12 @@ Use the best preprocessing choices from Phase 2. The placeholders below assume 2
|
|||||||
- lr: 1e-4
|
- lr: 1e-4
|
||||||
- weight_decay: 1e-4
|
- weight_decay: 1e-4
|
||||||
- image_size: 224
|
- image_size: 224
|
||||||
- face_crop: true (or best from Phase 2B/E)
|
- augment: false (placeholder until Phase 2 results confirm)
|
||||||
- face_crop_margin: 0.6
|
|
||||||
- augment: false (or best from Phase 2D/E)
|
|
||||||
- subsample: 0.2
|
- subsample: 0.2
|
||||||
- seed: 42
|
- seed: 42
|
||||||
- early_stopping_patience: 5
|
- early_stopping_patience: 5
|
||||||
|
|
||||||
- [ ] Create `classifier/configs/phase3/p3_resnet50.json`
|
- [x] Create `classifier/configs/phase3/p3_resnet50.json`
|
||||||
- backbone: resnet50
|
- backbone: resnet50
|
||||||
- pretrained: true
|
- pretrained: true
|
||||||
- epochs: 15
|
- epochs: 15
|
||||||
@@ -351,14 +349,12 @@ Use the best preprocessing choices from Phase 2. The placeholders below assume 2
|
|||||||
- lr: 1e-4
|
- lr: 1e-4
|
||||||
- weight_decay: 1e-4
|
- weight_decay: 1e-4
|
||||||
- image_size: 224
|
- image_size: 224
|
||||||
- face_crop: true (or best from Phase 2B/E)
|
- augment: false (placeholder until Phase 2 results confirm)
|
||||||
- face_crop_margin: 0.6
|
|
||||||
- augment: false (or best from Phase 2D/E)
|
|
||||||
- subsample: 0.2
|
- subsample: 0.2
|
||||||
- seed: 42
|
- seed: 42
|
||||||
- early_stopping_patience: 5
|
- early_stopping_patience: 5
|
||||||
|
|
||||||
- [ ] Create `classifier/configs/phase3/p3_efficientnet_b0.json`
|
- [x] Create `classifier/configs/phase3/p3_efficientnet_b0.json`
|
||||||
- backbone: efficientnet_b0
|
- backbone: efficientnet_b0
|
||||||
- pretrained: true
|
- pretrained: true
|
||||||
- epochs: 15
|
- epochs: 15
|
||||||
@@ -366,44 +362,43 @@ Use the best preprocessing choices from Phase 2. The placeholders below assume 2
|
|||||||
- lr: 1e-4
|
- lr: 1e-4
|
||||||
- weight_decay: 1e-4
|
- weight_decay: 1e-4
|
||||||
- image_size: 224
|
- image_size: 224
|
||||||
- face_crop: true (or best from Phase 2B/E)
|
- augment: false (placeholder until Phase 2 results confirm)
|
||||||
- augment: false (or best from Phase 2D/E)
|
|
||||||
- subsample: 0.2
|
- subsample: 0.2
|
||||||
- seed: 42
|
- seed: 42
|
||||||
- early_stopping_patience: 5
|
- early_stopping_patience: 5
|
||||||
|
|
||||||
- [ ] Create `classifier/configs/phase3/p3_convnext_tiny.json`
|
- [x] Create `classifier/configs/phase3/p3_convnext_tiny.json`
|
||||||
- backbone: convnext_tiny
|
- backbone: convnext_tiny
|
||||||
- pretrained: true
|
- pretrained: true
|
||||||
- epochs: 15
|
- epochs: 15
|
||||||
- batch_size: 32
|
- batch_size: 32
|
||||||
- lr: 1e-4
|
- lr: 5e-5 (reduced for ConvNeXt stability)
|
||||||
- weight_decay: 1e-4
|
- weight_decay: 1e-4
|
||||||
- image_size: 224
|
- image_size: 224
|
||||||
- face_crop: true (or best from Phase 2B/E)
|
- augment: false (placeholder until Phase 2 results confirm)
|
||||||
- augment: false (or best from Phase 2D/E)
|
|
||||||
- subsample: 0.2
|
- subsample: 0.2
|
||||||
- seed: 42
|
- seed: 42
|
||||||
- early_stopping_patience: 5
|
- early_stopping_patience: 5
|
||||||
|
|
||||||
- [ ] Create `classifier/configs/phase3/p3_mobilenetv3_small.json`
|
- [x] Create `classifier/configs/phase3/p3_mobilenetv3_small.json`
|
||||||
- backbone: mobilenetv3_small
|
- backbone: mobilenet_v3_small
|
||||||
- pretrained: true
|
- pretrained: true
|
||||||
- epochs: 15
|
- epochs: 15
|
||||||
- batch_size: 32
|
- batch_size: 32
|
||||||
- lr: 1e-4
|
- lr: 1e-4
|
||||||
- weight_decay: 1e-4
|
- weight_decay: 1e-4
|
||||||
- image_size: 224
|
- image_size: 224
|
||||||
- face_crop: true (or best from Phase 2B/E)
|
- augment: false (placeholder until Phase 2 results confirm)
|
||||||
- augment: false (or best from Phase 2D/E)
|
|
||||||
- subsample: 0.2
|
- subsample: 0.2
|
||||||
- seed: 42
|
- seed: 42
|
||||||
- early_stopping_patience: 5
|
- early_stopping_patience: 5
|
||||||
|
|
||||||
|
- [x] Remove `p3a_mobilenet_v3_large.json` (not in plan, MobileNet V3 Large fills no distinct niche)
|
||||||
|
|
||||||
### 3.2 Model Implementation
|
### 3.2 Model Implementation
|
||||||
- [ ] Implement ConvNeXt-Tiny in `classifier/src/models/convnext.py`
|
- [x] Implement ConvNeXt-Tiny in `classifier/src/models/convnext.py`
|
||||||
- [ ] Implement MobileNetV3-Small in `classifier/src/models/mobilenet.py`
|
- [x] Implement MobileNetV3-Small in `classifier/src/models/mobilenet.py`
|
||||||
- [ ] Register both models in `classifier/src/models/__init__.py`
|
- [x] Register both models in `classifier/src/models/__init__.py`
|
||||||
|
|
||||||
### 3.3 Training
|
### 3.3 Training
|
||||||
- [ ] Train ResNet34 with 5-fold stratified group CV
|
- [ ] Train ResNet34 with 5-fold stratified group CV
|
||||||
@@ -570,9 +565,9 @@ This section is the consolidated notebook checklist for the notebooks referenced
|
|||||||
- [x] Rename `classifier/run_cv.py` to `classifier/run.py` (pipeline expects classifier/run.py)
|
- [x] Rename `classifier/run_cv.py` to `classifier/run.py` (pipeline expects classifier/run.py)
|
||||||
|
|
||||||
### Model Implementations
|
### Model Implementations
|
||||||
- [ ] Implement ConvNeXt-Tiny in `classifier/src/models/convnext.py`
|
- [x] Implement ConvNeXt-Tiny in `classifier/src/models/convnext.py`
|
||||||
- [ ] Implement MobileNetV3-Small in `classifier/src/models/mobilenet.py`
|
- [x] Implement MobileNetV3-Small in `classifier/src/models/mobilenet.py`
|
||||||
- [ ] Register both models in `classifier/src/models/__init__.py`
|
- [x] Register both models in `classifier/src/models/__init__.py`
|
||||||
|
|
||||||
### Normalization Implementation
|
### Normalization Implementation
|
||||||
- [ ] Implement function to calculate mean/std from real training images only
|
- [ ] Implement function to calculate mean/std from real training images only
|
||||||
@@ -589,9 +584,9 @@ This section is the consolidated notebook checklist for the notebooks referenced
|
|||||||
- [ ] Implement pairwise source AUC variance calculations
|
- [ ] Implement pairwise source AUC variance calculations
|
||||||
|
|
||||||
### Grad-CAM Improvements
|
### Grad-CAM Improvements
|
||||||
- [ ] Ensure Grad-CAM works for all model types (CNN-based)
|
- [x] Ensure Grad-CAM works for all model types (CNN-based)
|
||||||
- [ ] Implement Grad-CAM for ConvNeXt
|
- [x] Implement Grad-CAM for ConvNeXt (last Conv2d found automatically by `find_conv()`)
|
||||||
- [ ] Implement Grad-CAM for MobileNetV3
|
- [x] Implement Grad-CAM for MobileNetV3 (last Conv2d found automatically by `find_conv()`)
|
||||||
- [ ] Organize Grad-CAM outputs by experiment, model, prediction type, source
|
- [ ] Organize Grad-CAM outputs by experiment, model, prediction type, source
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
Reference in New Issue
Block a user