Download visuals/finetuning_walkthrough_transcript.md from Dhruv1000/TSRDA: direct link, hf CLI and curl.
- Browser
- Download file 10.8 kB
-
https://huggingface.co/Dhruv1000/TSRDA/resolve/main/visuals/finetuning_walkthrough_transcript.md
- Command line
-
hf download hf://Dhruv1000/TSRDA/visuals/finetuning_walkthrough_transcript.md
-
curl -L -o finetuning_walkthrough_transcript.md https://huggingface.co/Dhruv1000/TSRDA/resolve/main/visuals/finetuning_walkthrough_transcript.md
Animation transcript
All animated arrows are schematic. Scores are historical measurements, not simulated training curves.
1. Read the unlabeled satellite sequence
Stage: Pretraining. 496 fold5 patches; crop labels are not loaded.
- PASTISPatchDataset: load_target=False; normalize ten bands
- Sixteen fixed tiles: 4×4 grid; each tile is32×32
- Separate crop updates: Batch4; 1,984 optimizer steps/epoch
Pretraining learns a representation of spectral and temporal structure. It does not directly learn the eighteen crop labels.
Code: pretrain.py: main() → dataset.py: crop_ij().
2. Mask eligible observations
Stage: Pretraining. Historical NDVI-style frame gate, calculated on normalized bands.
- Eligibility gate: NDVI index6/2 >0.2; vegetation fraction >0.9
- Random spatial mask: Nominal40% masking in eligible frames
- Learned mask token: Same pixel mask spans all ten spectral bands
Frames failing the gate remain visible. Controlled pilots found roughly3% effective masking; nominal40% is not whole-dataset coverage.
Code: model.py: UTAEPrediction.forward().
3. Reconstruct the hidden spectral values
Stage: Pretraining. The encoder sees corrupted inputs and predicts original ten-band values.
- Spatial encoder: Full-resolution convolutions + ASPP + SE
- Temporal encoder: Three reduced dual-attention blocks
- Reconstruction head: Linear256→10 at every pixel and time
Masked-value mean-squared error supplies the gradients. The auxiliary reconstruction head exists, but DEEP_SUP=False disables its extra loss.
Code: UTAE_ASPP.forward() → UTAEPrediction.forward().
4. Save the encoder checkpoint
Stage: Pretraining. The supplied encoder artifact records epoch99.
- latest.tar: Full wrapper + optimizer/scaler/RNG state
- latest.utae.tar: Encoder weights only
- Transferable representation: Original pretrained folder retained untouched
We used the supplied pretrained artifact. This animation is not a claim that its original100-epoch pretraining was rerun in this session.
Code: pretrain.py: main() → torch.save().
5. Load your encoder; attach the supervised task
Stage: Fine-tuning. Reconstruction heads are replaced by a segmentation wrapper.
- Strict encoder load: Reuse spatial + temporal pretrained weights
- Fresh supervised layers: STA, semantic, boundary, gated refinement
- Train the complete model: Encoder and new layers both receive gradients
At the original supervised start, the task layers are new. Later continuation stages load the entire selected fine-tuned model, including its heads.
Code: train_spatial_temporal.py: main() / --init_finetuned.
6. Keep the labeled sampling protocol fixed
Stage: Fine-tuning. Training fold1:76 entries /72 unique; validation fold2:76/71.
- Batch of2 patches: X:2×T×10×128×128; preserve duplicate IDs
- Two fixed diagonal crops: [0:32,0:32] and [32:64,32:64]
- 76 updates per epoch: 38 batches ×2 separate crop steps
Training transforms operate inside these selected windows. Validation uses the same fixed windows without those random transformations.
Code: dataset.py: pad_collate(), crop_ij().
7. Apply the recorded training transforms
Stage: Fine-tuning. Augmentations are method-specific; sample IDs and crop windows stay fixed.
- Spatial transform: Paired flips /90-degree rotations of X and Y
- Temporal transform: Observation subsampling and frame dropout
- Spectral transform: Per-band gain/bias jitter plus noise
Subsampling keeps the retained observation positions. Label geometry follows the spatial transformation; validation and test are not augmented.
Code: aug_dihedral(), aug_temporal_subsample(), aug_frame_dropout(), aug_spectral().
8. Extract spatial features for every acquisition
Stage: Fine-tuning. The spatial encoder preserves H×W instead of downsampling the crop.
- Stem10→64: 3×3 convolution; second convolution dilation2
- ASPP64→256: Dilations1/2/4 plus global pooling
- Channel attention: SE weighting; reshape to per-pixel sequences
Each pixel now has a256-dimensional feature vector at every acquisition. Spatial context and temporal modeling have separate roles.
Code: AtrousSpatialEncoder.forward() / ASPP.forward().
9. Model crop evolution with temporal dual attention
Stage: Fine-tuning. Index positions are encoded; actual acquisition-day gaps are not used.
- Reduced KV tokens: 256→64; group4 observations→256
- Two attention operations: Reduced self-attention; full-T queries to reduced KV
- Three residual blocks: Eight heads; GELU + parallel depthwiseConv1D MLP
The winning backbone preserves its original padding behavior. Explicit padding-mask variants existed, but they are not the deployed encoder.
Code: TemporalSRDABlock.forward() / TemporalSRDAEncoder.forward().
10. Collapse time and predict class / boundary outputs
Stage: Fine-tuning. STA pools time; three spatial convolutions refine the pooled map.
- Learned temporal pooling: softmax scores over T → weighted feature sum
- Semantic + boundary heads: 20 class logits and1 boundary logit
- Gated refinement: Features ×(1+sigmoid(boundary)); residual class correction
Boundary predictions directly affect the refined class logits inside the network. They are not an external mask-cleaning stage.
Code: STA.forward() → UTAEClassificationDual.forward().
11. Compute the supervised objective
Stage: Fine-tuning. Two segmentation losses and auxiliary boundary supervision.
- Semantic objective: CE +0.75 Lovász
- Refined objective: CE +0.75 Lovász
- Boundary objective: 0.5 BCE; local max/min label-gradient target
CE/Lovász ignore GT0/19; label smoothing0.05. Boundary BCE is applied to the constructed boundary map without that foreground mask.
Code: training_loss(), compute_boundary_target(), LovaszSoftmaxLoss.forward().
12. Backpropagate; update encoder and task layers
Stage: Fine-tuning. AdamW parameter groups give the encoder a lower learning rate.
- Gradient computation: FP16 forward + GradScaler backward
- Stabilize the update: Unscale gradients; clip norm5
- Parameter update: Encoder LR0.5×head LR; update EMA copy
Raw and EMA weights are evaluated, but the final SAM component uses the selected raw checkpoint. EMA maintenance is not proof of an EMA gain.
Code: build_param_groups(), lr_factor(), ModelEMA.update().
13. Continue from the low-learning-rate checkpoint
Stage: SAM refinement. Same architecture and losses; change the optimization step.
- Selected low-LR model: Load encoder AND supervised heads
- Low learning rates: Head1e-5; encoder5e-6
- SAM budget: 20 epochs; radius0.02; batch2; fixed32
The SAM run starts from a previously fine-tuned checkpoint, not directly from a bare pretrained encoder. Its optimizer and schedule start fresh.
Code: main(): --init_finetuned ... --research sam.
14. First SAM pass: find a weight perturbation
Stage: SAM refinement. Calculate the gradient at current weights θ.
- Loss atθ: Forward → loss → backward
- Normalize gradient: g /(||g|| + epsilon)
- Temporary perturbation: θtemporary = θ +0.02 ×normalized gradient
This is Sharpness-Aware Minimization. No Segment Anything encoder, prompt, mask generator, or extra architecture is introduced.
Code: train_spatial_temporal.py: main(), research==sam branch.
15. Second SAM pass: restore and update
Stage: SAM refinement. Compute a new gradient at the temporarily perturbed weights.
- Second loss/backward: Same crop; BatchNorm held in eval mode
- Restore originalθ: Subtract stored perturbations
- AdamW update: Apply second-pass gradient; update scaler/EMA
Select raw epoch11 using validation. Once saved, the network needs only its ordinary forward pass at inference.
Code: research==sam: offsets → second_loss → restore → scaler.step().
16. Freeze the SAM encoder and collect earlier features
Stage: Feature clusters. Reuse its first temporal block, rather than training another encoder.
- Forward hook: DepthCollector captures block1 output
- Valid-time statistics: Mean256 +standard deviation256 =vector512
- Training normalization: Fit mean/std on training features; then L2 normalize
The readout shares the network forward pass. Hooks summarize real features; the diagram does not visualize measured feature activations.
Code: DepthCollector.begin(), hook(), end(); train_normalizer().
17. Fit three feature-cluster centres per crop class
Stage: Feature clusters. Use labeled training pixels only; no validation/test labels fit centres.
- Balanced memory: 32 pixels per supporting training patch/class
- KMeans fitting: 18 classes ×3 centres; seed3407; n_init3
- Similarity classifier: Similarity/0.1 → logsumexp over3 → softmax18
Repeated patch/crop occurrences are deduplicated for the memory bank only. The supervised dataset list itself retains duplicate entries.
Code: make_prototypes() / probability().
18. Train the original independent temporal specialist
Stage: Temporal CNNs. A small model of each pixel’s spectral evolution, trained from scratch.
- Input projection: T×10 → T×64; valid-time mask
- Four Conv1D blocks: Kernel3; depthwise; dilation1/2/4/8
- Mean +max classifier: Vector128 →64 →18 crop classes
100 epochs; AdamW1e-3, WD0.01, CE smoothing0.05, warmup3/cosine. Combine25% CNN probabilities with75% SAM/cluster blend.
Code: TemporalCNN.forward(); historical original CNN training.
19. Add the new plain-CNN control
Stage: Temporal CNNs. A separate training run with the same architecture and seed value.
- Matched control: Same data, fixed32 crops,100-epoch budget
- Distinct training trajectory: New trainer resets RNG after model construction
- Validation-selected blend: 75% reference +25% new CNN probabilities
The CNN is weaker alone but changes useful class rankings. A matched attention alternative replaces mean pooling and adds65 parameters.
Code: train_temporal_cnn.py: train(); AttentionCNN.forward().
20. Run the complete system on full128 test patches
Stage: Final evaluation. 482 fold4 patches; no TTA or external mask post-processing.
- Four probability sources: SAM /shared-feature clusters /old CNN /new CNN
- Recommended weights: 28.125% /28.125% /18.75% /25%
- Final argmax +metrics: Full20×20 matrix; score GT classes1–18
Recommended: validation52.5640%, test49.4555%. Attention alternative: validation51.8368%, highest observed test49.5298%; reported separately.
Code: evaluate.py: load_models(), main(); metrics_cm().