Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .github/workflows/2d_model_ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# .github/workflows/2d_model_ci.yml
# =========================================================================
# CI Pipeline: 2D Model Tensor Shape Validation
# Runs on every push to feature/2d-models to catch tensor shape mismatches
# before they propagate into model training code.
# =========================================================================

name: 2D Model CI Pipeline

on:
push:
branches: [feature/2d-models]
pull_request:
branches: [main, feature/2d-models]

jobs:
validate-2d-shapes:
name: 2D Tensor Shape Validation
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"

- name: Cache pip dependencies
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-2d-${{ hashFiles('requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-2d-

- name: Install dependencies (CPU-only PyTorch for CI speed)
run: |
python -m pip install --upgrade pip
pip install torch --index-url https://download.pytorch.org/whl/cpu
pip install numpy scipy scikit-learn matplotlib

- name: Run 2D shape validation tests
run: python test_2d_shapes.py
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ data/
.DS_Store
Thumbs.db

stft_dataset.npz
stft_dataset.npz
*.onnx
81 changes: 81 additions & 0 deletions benchmark_2d.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import torch
import time
from models_2d import ResNet18_2D, STFTRADN

def measure_latency(model, input_shape, num_runs=100, warmup_runs=10):
"""Measures the inference latency per sample in milliseconds."""
device = next(model.parameters()).device
dummy_input = torch.randn(input_shape).to(device)

model.eval()

# Warmup
with torch.no_grad():
for _ in range(warmup_runs):
_ = model(dummy_input)

# Measure
start_time = time.perf_counter()
with torch.no_grad():
for _ in range(num_runs):
_ = model(dummy_input)
end_time = time.perf_counter()

total_time_ms = (end_time - start_time) * 1000
latency_per_sample_ms = total_time_ms / (num_runs * input_shape[0])
return latency_per_sample_ms

def count_trainable_parameters(model):
"""Calculates the total trainable parameter footprint."""
return sum(p.numel() for p in model.parameters() if p.requires_grad)

def export_to_onnx(model, input_shape, filename="stft_radn_model.onnx"):
"""Exports the model weights to an ONNX file."""
device = next(model.parameters()).device
dummy_input = torch.randn(input_shape).to(device)
model.eval()

torch.onnx.export(
model,
dummy_input,
filename,
export_params=True,
opset_version=12,
do_constant_folding=True,
input_names=['input'],
output_names=['output'],
dynamic_axes={'input': {0: 'batch_size'}, 'output': {0: 'batch_size'}}
)
print(f"[INFO] Model exported successfully to {filename}")

if __name__ == "__main__":
# Standard input shape: [Batch, Channels, Height, Width]
# Corresponding to [1, 1, 64, 5] for grayscale 2D spectrograms
input_shape = (1, 1, 64, 5)

print("="*60)
print("Initializing Models...")
resnet_model = ResNet18_2D(num_classes=11, in_channels=1)
stft_model = STFTRADN(num_classes=11, in_channels=1)

print("="*60)
print(" ResNet18_2D Benchmarks")
print("="*60)
resnet_params = count_trainable_parameters(resnet_model)
print(f"Trainable Parameters : {resnet_params:,}")
resnet_latency = measure_latency(resnet_model, input_shape)
print(f"Inference Latency : {resnet_latency:.4f} ms / sample")

print("\n" + "="*60)
print(" STFTRADN Benchmarks")
print("="*60)
stft_params = count_trainable_parameters(stft_model)
print(f"Trainable Parameters : {stft_params:,}")
stft_latency = measure_latency(stft_model, input_shape)
print(f"Inference Latency : {stft_latency:.4f} ms / sample")

print("\n" + "="*60)
print(" ONNX Export (STFTRADN for Grad-CAM validation)")
print("="*60)
export_to_onnx(stft_model, input_shape, filename="stft_radn_model.onnx")
print("="*60)
Loading
Loading