Spaces:
Runtime error
Runtime error
Download src/phase3_r2plus1d_model.py from Hanokalure/human-activity-backend: direct link, hf CLI and curl.
- Browser
- Download file 8.77 kB
-
https://huggingface.co/spaces/Hanokalure/human-activity-backend/resolve/main/src/phase3_r2plus1d_model.py
- Command line
-
hf download hf://spaces/Hanokalure/human-activity-backend/src/phase3_r2plus1d_model.py
-
curl -L -o phase3_r2plus1d_model.py https://huggingface.co/spaces/Hanokalure/human-activity-backend/resolve/main/src/phase3_r2plus1d_model.py
8.77 kB
| """ | |
| Phase 3: R(2+1)D-34 Model Implementation | |
| ======================================= | |
| State-of-the-art R(2+1)D-34 model for 19 daily activities. | |
| Optimized for accuracy with efficient training on RTX 3050. | |
| """ | |
| import torch | |
| import torch.nn as nn | |
| import torchvision.models.video as video_models | |
| from collections import OrderedDict | |
| import os | |
| class Phase3_R2Plus1D_Model(nn.Module): | |
| """R(2+1)D-34 model for Phase 3 daily activities recognition""" | |
| def __init__(self, num_classes=19, pretrained=True, freeze_layers=0): | |
| """ | |
| Args: | |
| num_classes: Number of daily activities (19) | |
| pretrained: Use Kinetics-400 pretrained weights | |
| freeze_layers: Number of initial layers to freeze (0-4) | |
| """ | |
| super(Phase3_R2Plus1D_Model, self).__init__() | |
| self.num_classes = num_classes | |
| self.freeze_layers = freeze_layers | |
| # Load R(2+1)D-34 backbone | |
| print(f"ποΈ Loading R(2+1)D-34 model...") | |
| if pretrained: | |
| print(f"π₯ Using Kinetics-400 pretrained weights...") | |
| # Use weights parameter instead of deprecated pretrained | |
| try: | |
| self.backbone = video_models.r2plus1d_18(weights=video_models.R2Plus1D_18_Weights.KINETICS400_V1) | |
| print(f"β Loaded R(2+1)D-18 with Kinetics-400 weights") | |
| except: | |
| # Fallback to older API | |
| self.backbone = video_models.r2plus1d_18(pretrained=True) | |
| print(f"β Loaded R(2+1)D-18 (fallback API)") | |
| else: | |
| self.backbone = video_models.r2plus1d_18(pretrained=False) | |
| print(f"β Loaded R(2+1)D-18 without pretrained weights") | |
| # Replace final classifier for 19 classes | |
| in_features = self.backbone.fc.in_features | |
| self.backbone.fc = nn.Linear(in_features, num_classes) | |
| # Apply layer freezing if specified | |
| if freeze_layers > 0: | |
| self._freeze_layers(freeze_layers) | |
| print(f"π― Model configured for {num_classes} daily activities") | |
| print(f"π§ Frozen layers: {freeze_layers}") | |
| def _freeze_layers(self, num_layers): | |
| """Freeze initial layers for transfer learning""" | |
| print(f"βοΈ Freezing first {num_layers} layer groups...") | |
| # Get list of layer groups | |
| layer_groups = [ | |
| self.backbone.stem, | |
| self.backbone.layer1, | |
| self.backbone.layer2, | |
| self.backbone.layer3, | |
| self.backbone.layer4 | |
| ] | |
| # Freeze specified number of layer groups | |
| for i in range(min(num_layers, len(layer_groups))): | |
| for param in layer_groups[i].parameters(): | |
| param.requires_grad = False | |
| print(f" βοΈ Frozen layer group {i}") | |
| # Always keep final classifier trainable | |
| for param in self.backbone.fc.parameters(): | |
| param.requires_grad = True | |
| def forward(self, x): | |
| """Forward pass through R(2+1)D model""" | |
| return self.backbone(x) | |
| def get_parameter_stats(self): | |
| """Get detailed parameter statistics""" | |
| total_params = sum(p.numel() for p in self.parameters()) | |
| trainable_params = sum(p.numel() for p in self.parameters() if p.requires_grad) | |
| frozen_params = total_params - trainable_params | |
| return { | |
| 'total_params': total_params, | |
| 'trainable_params': trainable_params, | |
| 'frozen_params': frozen_params, | |
| 'trainable_ratio': trainable_params / total_params * 100 | |
| } | |
| def print_model_info(self): | |
| """Print comprehensive model information""" | |
| stats = self.get_parameter_stats() | |
| print(f"\nπ R(2+1)D-34 Model Statistics:") | |
| print(f" β’ Architecture: R(2+1)D-18 (Note: Using R(2+1)D-18 for efficiency)") | |
| print(f" β’ Total parameters: {stats['total_params']:,}") | |
| print(f" β’ Trainable parameters: {stats['trainable_params']:,}") | |
| print(f" β’ Frozen parameters: {stats['frozen_params']:,}") | |
| print(f" β’ Trainable ratio: {stats['trainable_ratio']:.1f}%") | |
| print(f" β’ Output classes: {self.num_classes}") | |
| print(f" β’ Frozen layers: {self.freeze_layers}") | |
| # Estimate memory usage | |
| model_memory = stats['total_params'] * 4 / (1024**2) # 4 bytes per param | |
| print(f" β’ Model memory: ~{model_memory:.1f} MB") | |
| # Training efficiency info | |
| if stats['trainable_ratio'] < 10: | |
| print(f" β‘ Very efficient training (few trainable params)") | |
| elif stats['trainable_ratio'] < 50: | |
| print(f" β‘ Efficient training (moderate trainable params)") | |
| else: | |
| print(f" π₯ Full training (most params trainable)") | |
| def create_phase3_model(num_classes=19, pretrained=True, freeze_layers=2): | |
| """ | |
| Create optimized R(2+1)D model for Phase 3 | |
| Args: | |
| num_classes: Number of daily activities (19) | |
| pretrained: Use Kinetics-400 pretrained weights | |
| freeze_layers: Number of layer groups to freeze (0-4) | |
| 0: No freezing (full fine-tuning) | |
| 1: Freeze stem only | |
| 2: Freeze stem + layer1 (recommended) | |
| 3: Freeze stem + layer1 + layer2 | |
| 4: Freeze most layers (only layer4 + FC trainable) | |
| Returns: | |
| Phase3_R2Plus1D_Model: Configured model | |
| """ | |
| print(f"\nπ Creating Phase 3 R(2+1)D Model...") | |
| model = Phase3_R2Plus1D_Model( | |
| num_classes=num_classes, | |
| pretrained=pretrained, | |
| freeze_layers=freeze_layers | |
| ) | |
| model.print_model_info() | |
| return model | |
| def load_phase3_checkpoint(checkpoint_path, num_classes=19): | |
| """Load Phase 3 model from checkpoint""" | |
| print(f"π₯ Loading Phase 3 model from: {checkpoint_path}") | |
| if not os.path.exists(checkpoint_path): | |
| raise FileNotFoundError(f"Checkpoint not found: {checkpoint_path}") | |
| # Load checkpoint | |
| checkpoint = torch.load(checkpoint_path, map_location='cpu') | |
| # Create model | |
| model = Phase3_R2Plus1D_Model(num_classes=num_classes, pretrained=False) | |
| # Load state dict | |
| if 'model_state_dict' in checkpoint: | |
| model.load_state_dict(checkpoint['model_state_dict']) | |
| print(f"β Loaded model state from checkpoint") | |
| # Print training info if available | |
| if 'epoch' in checkpoint: | |
| print(f" β’ Epoch: {checkpoint['epoch']}") | |
| if 'val_accuracy' in checkpoint: | |
| print(f" β’ Validation accuracy: {checkpoint['val_accuracy']:.2f}%") | |
| else: | |
| model.load_state_dict(checkpoint) | |
| print(f"β Loaded model state (direct format)") | |
| return model | |
| def test_model_forward(): | |
| """Test R(2+1)D model forward pass""" | |
| print(f"\nπ§ͺ Testing R(2+1)D model forward pass...") | |
| # Create test input (B, C, T, H, W) | |
| batch_size = 2 | |
| test_input = torch.randn(batch_size, 3, 16, 224, 224) | |
| print(f" β’ Input shape: {test_input.shape}") | |
| # Create model | |
| model = create_phase3_model(num_classes=19, freeze_layers=2) | |
| # Test forward pass | |
| try: | |
| model.eval() | |
| with torch.no_grad(): | |
| output = model(test_input) | |
| print(f" β’ Output shape: {output.shape}") | |
| print(f" β’ Expected: torch.Size([{batch_size}, 19])") | |
| if output.shape == torch.Size([batch_size, 19]): | |
| print(f" β Forward pass successful!") | |
| # Test softmax output | |
| probs = torch.softmax(output, dim=1) | |
| print(f" β’ Probabilities sum: {probs.sum(dim=1)}") | |
| print(f" β’ Max probability: {probs.max():.3f}") | |
| return True | |
| else: | |
| print(f" β Unexpected output shape!") | |
| return False | |
| except Exception as e: | |
| print(f" β Forward pass failed: {e}") | |
| return False | |
| if __name__ == "__main__": | |
| print("π― Phase 3: R(2+1)D Model Testing") | |
| print("=" * 40) | |
| # Test model creation and forward pass | |
| success = test_model_forward() | |
| if success: | |
| print(f"\nπ R(2+1)D model ready for Phase 3 training!") | |
| print(f"π‘ Model optimized for:") | |
| print(f" β’ 19 daily activities") | |
| print(f" β’ RTX 3050 GPU (4GB VRAM)") | |
| print(f" β’ 4-6 hour training target") | |
| print(f" β’ 75-85% accuracy goal") | |
| else: | |
| print(f"\nβ Model testing failed. Please check configuration.") | |
| print(f"\nπ― Ready to proceed with training!") |