Repository navigation
Feature/1d model p2 - CNN & CNN_Transformer - #4
Merged
Merged
Conversation
…suite
- subsystem2_1d/__init__.py: expose public API for normalize_1d_iq,
IQAugmentation, RFSignalDataset1D, and get_1d_dataloaders
- subsystem2_1d/normalization_1d.py:
* normalize_1d_iq() - per-instance, per-channel zero-mean/unit-variance
normalization for single (2,128) and batched (N,2,128) numpy arrays
* IQAugmentation class - AWGN noise injection and random phase rotation
for on-the-fly data augmentation during training; master enable/disable switch
- subsystem2_1d/dataloader_1d.py:
* RFSignalDataset1D - PyTorch Dataset wrapping pre-sliced numpy arrays
with shape guard (2,128) and optional transform hook
* get_1d_dataloaders() - factory that reads Person 1s locked split indices
(train_idx.npy / val_idx.npy / test_idx.npy) and returns three DataLoaders
with shuffle=True for train only; Windows-safe num_workers handling
- subsystem2_1d/test_dataloader.py:
* Group A (22 tests, no data files needed): normalization correctness,
augmentation output shapes, L2-norm preservation, shape guards
* Group B (4 tests, requires data/X_all.npy): full DataLoader init,
batch shape assertions, split size checks, zero-index-overlap verification
* All 22 runnable tests PASS; 4 skipped pending dataset_agent.py run
- .gitignore: add rules to exclude subsystem2_1d/checkpoints/* and
subsystem2_1d/results/* while preserving .gitkeep directory stubs
Does NOT modify any files by Person 1 or Person 3.
- subsystem2_1d/classifiers_1d.py:
* CNN1DClassifier: 4-block deep 1D CNN with progressive feature extraction
- Block 1: Conv1d(2->64, k=7, same) -> BN -> ReLU -> MaxPool2 => (B,64,64)
- Block 2: Conv1d(64->128,k=5, same) -> BN -> ReLU -> MaxPool2 => (B,128,32)
- Block 3: Conv1d(128->256,k=3,same) -> BN -> ReLU -> MaxPool2 => (B,256,16)
- Block 4: Conv1d(256->256,k=3,same) -> BN -> ReLU -> MaxPool2 => (B,256,8)
- FC head: Flatten -> Linear(2048->256) -> BN -> ReLU -> Dropout(0.5) -> Linear(256->11)
- Total trainable params: 865,803
* CNNTransformerHybrid: strided CNN frontend + sinusoidal PE + TransformerEncoder
- CNN frontend (strided): Conv1d(2->64,k=7,s=2) -> Conv1d(64->128,k=5,s=2) => (B,128,32)
- Transpose => (B,32,128); d_model=128, nhead=8, dim_per_head=16
- PositionalEncoding: sinusoidal fixed embeddings, batch-first, dropout=0.1
- TransformerEncoder: num_layers=2, nhead=8, dim_feedforward=256, batch_first=True
- Global avg pool over sequence dim => (B,128); Linear(128->11)
- Total trainable params: 308,619
* PositionalEncoding: standalone nn.Module with register_buffer PE table
* build_model() factory: instantiate models by string key with **kwargs passthrough
* get_param_count() utility on both model classes
* Shape contract enforced: input (B,2,128) -> output (B,11)
- subsystem2_1d/test_classifiers.py: 11-section, 41-assertion test suite
* T-1/T-2: import paths (direct module + __init__.py public API)
* T-3: instantiation smoke tests for both architectures
* T-4: forward pass output shape [32, 11] verified for both models
* T-5: variable batch sizes {1, 16, 64} all produce correct shapes
* T-6: CNN1D intermediate shapes at every MaxPool block verified
* T-7: Hybrid intermediate shapes (CNN frontend, transpose, PE, Transformer, GAP)
* T-8: PositionalEncoding shape, non-trivial encoding, [-1,1] bounds
* T-9: param counts (CNN1D 865,803 > Hybrid 308,619; both in expected ranges)
* T-10: build_model factory and KeyError on unknown model name
* T-11: gradient flow back to input (model is differentiable)
* Result: 41/41 PASS
- subsystem2_1d/__init__.py: extended public API to include
CNN1DClassifier, CNNTransformerHybrid, PositionalEncoding, build_model
Does NOT modify any files by Person 1 or Person 3.
train_1d.py -- Full training loop
- AdamW optimizer (lr=1e-3, wd=1e-4) + CrossEntropyLoss
- ReduceLROnPlateau scheduler (factor=0.5, patience=3)
- EarlyStopping class: configurable patience + min_delta, reset(), step()
- Gradient clipping (max_norm=1.0) for training stability
- Best-checkpoint saving to subsystem2_1d/checkpoints/best_<model>.pt
- TrainingConfig dataclass (model_name, epochs, lr, wd, patience, ckpt_dir)
- train_model() importable function + argparse CLI (--model/--batch_size/--epochs/--lr)
- Epoch log: Epoch | TrainLoss | TrainAcc | ValLoss | ValAcc | LR | Status
eval_1d.py -- Scientifically rigorous evaluation
- Multi-SNR accuracy: all 20 levels (-20 to +18 dB, step 2 dB)
- Per-SNR accuracy table printed + exported as JSON (accuracy_vs_snr_<model>.json)
for Person 4 joint plotting on Day 7
- Confusion matrices at -10, 0, +10 dB SNR:
* Row-normalised PNG heatmap with cell count annotations
* Raw numpy .npy array (shape 11x11)
* Fixed safe-denominator normalisation (no RuntimeWarning on empty rows)
- CPU inference latency profiling: 100 warm-up + 200 timed passes (ms/sample)
- load_model_from_checkpoint() factory
- print_edge_suitability_report() side-by-side comparison table
- Headless-safe: matplotlib.use('Agg') before pyplot import
- argparse CLI: --model --checkpoint --data_dir --batch_size
test_training_pipeline.py -- 85-assertion end-to-end pipeline test
- T-1: EarlyStopping unit tests (13 assertions)
improvement, counter increment, patience trigger, late improvement, reset()
- T-2/T-3: Training smoke tests -- CNN1DClassifier + CNNTransformerHybrid (2 epochs)
gradient flow (params differ from initial state), checkpoint saved/loadable,
history dict structure, finite losses, accuracies in [0,1]
- T-4/T-5: Evaluation dry-runs -- both architectures
JSON with all 20 SNR keys, CM .npy files at -10/0/+10 dB (shape 11x11,
integer dtype, correct sample count), CM .png files, latency > 0,
overall accuracy in [0,1]
- All I/O to tempfile.mkdtemp() -- nothing written to real checkpoints/results/
- Result: 85/85 PASS, EXIT:0, zero warnings
subsystem2_1d/__init__.py: extended public API
- Added: EarlyStopping, TrainingConfig, train_model
- Added: evaluate_model, print_edge_suitability_report,
load_model_from_checkpoint, measure_inference_latency
Does NOT modify any files by Person 1, Person 3, or Person 4.
neilkdbn
approved these changes
Aug 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.