Spaces:
Sleeping
Sleeping
| """ | |
| HuggingFace Space: AST Training Dashboard | |
| Live monitoring and model card generation | |
| """ | |
| import gradio as gr | |
| import json | |
| import time | |
| from pathlib import Path | |
| import plotly.graph_objects as go | |
| from plotly.subplots import make_subplots | |
| try: | |
| from adaptive_sparse_training import AdaptiveSparseTrainer, ASTConfig | |
| import torch | |
| import torchvision | |
| import timm | |
| HAS_DEPS = True | |
| except ImportError: | |
| HAS_DEPS = False | |
| class ASTDashboard: | |
| """Real-time AST training dashboard""" | |
| def __init__(self): | |
| self.active_training = None | |
| self.training_history = [] | |
| def start_training( | |
| self, | |
| model_name: str, | |
| dataset: str, | |
| activation_rate: float, | |
| epochs: int, | |
| progress=gr.Progress() | |
| ): | |
| """Start AST training with live updates""" | |
| if not HAS_DEPS: | |
| return "β Dependencies not installed", None, None | |
| progress(0, desc="Initializing...") | |
| # Load dataset (CIFAR-10 for demo) | |
| train_loader, val_loader = self._get_dataloaders(dataset) | |
| # Create model | |
| progress(0.1, desc="Creating model...") | |
| if model_name == "resnet18": | |
| model = torchvision.models.resnet18(num_classes=10) | |
| else: | |
| model = timm.create_model(model_name, pretrained=False, num_classes=10) | |
| # AST Config (CPU mode for HuggingFace free tier) | |
| config = ASTConfig( | |
| target_activation_rate=activation_rate, | |
| use_amp=False, # Disable AMP on CPU | |
| device='cpu' | |
| ) | |
| # Start training | |
| progress(0.2, desc="Starting training...") | |
| model = model.to('cpu') | |
| trainer = AdaptiveSparseTrainer(model, train_loader, val_loader, config) | |
| self.training_history = [] | |
| for epoch in range(epochs): | |
| progress((epoch + 1) / epochs, desc=f"Epoch {epoch+1}/{epochs}") | |
| # Train one epoch | |
| epoch_stats = trainer.train_epoch(epoch) | |
| val_acc = trainer.evaluate() | |
| # Store history | |
| self.training_history.append({ | |
| "epoch": epoch + 1, | |
| "val_acc": val_acc, | |
| "activation_rate": epoch_stats.get("activation_rate", activation_rate), | |
| "threshold": epoch_stats.get("threshold", 1.0), | |
| }) | |
| # Update dashboard | |
| if (epoch + 1) % 5 == 0 or epoch == epochs - 1: | |
| status = self._format_status(epoch + 1, epochs, val_acc, activation_rate) | |
| plot = self._create_plot() | |
| yield status, plot, None | |
| # Generate model card | |
| model_card = self._generate_model_card(model_name, activation_rate) | |
| final_status = f"β Training complete! Best accuracy: {max([h['val_acc'] for h in self.training_history]):.2%}" | |
| yield final_status, self._create_plot(), model_card | |
| def _get_dataloaders(self, dataset: str): | |
| """Get data loaders (CIFAR-10 demo)""" | |
| import torchvision.transforms as transforms | |
| from torch.utils.data import DataLoader | |
| transform = transforms.Compose([ | |
| transforms.ToTensor(), | |
| transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) | |
| ]) | |
| train_dataset = torchvision.datasets.CIFAR10( | |
| root='./data', train=True, download=True, transform=transform | |
| ) | |
| val_dataset = torchvision.datasets.CIFAR10( | |
| root='./data', train=False, download=True, transform=transform | |
| ) | |
| train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True, num_workers=0) | |
| val_loader = DataLoader(val_dataset, batch_size=64, shuffle=False, num_workers=0) | |
| return train_loader, val_loader | |
| def _format_status(self, epoch: int, total_epochs: int, accuracy: float, activation_rate: float): | |
| """Format training status""" | |
| return f""" | |
| ### π Training in Progress | |
| **Epoch:** {epoch}/{total_epochs} | |
| **Accuracy:** {accuracy:.2%} | |
| **Activation Rate:** {activation_rate:.1%} | |
| **Energy Savings:** ~{(1-activation_rate)*100:.0f}% | |
| *Updating every 5 epochs...* | |
| """ | |
| def _create_plot(self): | |
| """Create live training plot""" | |
| if not self.training_history: | |
| return None | |
| fig = make_subplots( | |
| rows=2, cols=2, | |
| subplot_titles=("Validation Accuracy", "Activation Rate", "Threshold Evolution", "Energy Savings"), | |
| ) | |
| epochs = [h["epoch"] for h in self.training_history] | |
| accuracies = [h["val_acc"] * 100 for h in self.training_history] | |
| activation_rates = [h["activation_rate"] * 100 for h in self.training_history] | |
| thresholds = [h["threshold"] for h in self.training_history] | |
| savings = [(1 - h["activation_rate"]) * 100 for h in self.training_history] | |
| # Accuracy plot | |
| fig.add_trace( | |
| go.Scatter(x=epochs, y=accuracies, mode='lines+markers', name='Val Accuracy', | |
| line=dict(color='#3498db', width=3)), | |
| row=1, col=1 | |
| ) | |
| # Activation rate plot | |
| fig.add_trace( | |
| go.Scatter(x=epochs, y=activation_rates, mode='lines+markers', name='Activation Rate', | |
| line=dict(color='#e74c3c', width=3)), | |
| row=1, col=2 | |
| ) | |
| # Threshold plot | |
| fig.add_trace( | |
| go.Scatter(x=epochs, y=thresholds, mode='lines+markers', name='Threshold', | |
| line=dict(color='#f39c12', width=3)), | |
| row=2, col=1 | |
| ) | |
| # Energy savings plot | |
| fig.add_trace( | |
| go.Scatter(x=epochs, y=savings, mode='lines+markers', name='Energy Savings', | |
| line=dict(color='#27ae60', width=3), fill='tozeroy'), | |
| row=2, col=2 | |
| ) | |
| fig.update_xaxes(title_text="Epoch") | |
| fig.update_yaxes(title_text="Accuracy (%)", row=1, col=1) | |
| fig.update_yaxes(title_text="Activation (%)", row=1, col=2) | |
| fig.update_yaxes(title_text="Threshold", row=2, col=1) | |
| fig.update_yaxes(title_text="Savings (%)", row=2, col=2) | |
| fig.update_layout(height=600, showlegend=False) | |
| return fig | |
| def _generate_model_card(self, model_name: str, activation_rate: float): | |
| """Generate HuggingFace model card""" | |
| best_acc = max([h["val_acc"] for h in self.training_history]) | |
| energy_savings = (1 - activation_rate) * 100 | |
| return f"""--- | |
| tags: | |
| - adaptive-sparse-training | |
| - energy-efficient | |
| - sustainability | |
| metrics: | |
| - accuracy | |
| - energy_savings | |
| --- | |
| # {model_name} (AST-Trained) | |
| **Trained with {energy_savings:.0f}% less energy than standard training** β‘ | |
| ## Model Details | |
| - **Architecture:** {model_name} | |
| - **Dataset:** CIFAR-10 | |
| - **Training Method:** Adaptive Sparse Training (AST) | |
| - **Target Activation Rate:** {activation_rate:.0%} | |
| ## Performance | |
| - **Accuracy:** {best_acc:.2%} | |
| - **Energy Savings:** {energy_savings:.0f}% | |
| - **Training Epochs:** {len(self.training_history)} | |
| ## Sustainability Report | |
| This model was trained using Adaptive Sparse Training, which dynamically selects | |
| the most important training samples. This resulted in: | |
| - β‘ **{energy_savings:.0f}% energy savings** compared to standard training | |
| - π **Lower carbon footprint** | |
| - β±οΈ **Faster training time** | |
| - π― **Maintained accuracy** (minimal degradation) | |
| ## How to Use | |
| ```python | |
| import torch | |
| from torchvision import models | |
| # Load model | |
| model = models.{model_name}(num_classes=10) | |
| model.load_state_dict(torch.load("pytorch_model.bin")) | |
| model.eval() | |
| # Inference | |
| # ... (your inference code) | |
| ``` | |
| ## Training Details | |
| **AST Configuration:** | |
| - Target Activation Rate: {activation_rate:.0%} | |
| - Adaptive PI Controller: Enabled | |
| - Mixed Precision (AMP): Enabled | |
| ## Reproducing This Model | |
| ```bash | |
| pip install adaptive-sparse-training | |
| python -c " | |
| from adaptive_sparse_training import AdaptiveSparseTrainer, ASTConfig | |
| config = ASTConfig(target_activation_rate={activation_rate}) | |
| # ... (full training code) | |
| " | |
| ``` | |
| ## Citation | |
| If you use this model or AST, please cite: | |
| ```bibtex | |
| @software{{adaptive_sparse_training, | |
| title={{Adaptive Sparse Training}}, | |
| author={{Idiakhoa, Oluwafemi}}, | |
| year={{2024}}, | |
| url={{https://github.com/oluwafemidiakhoa/adaptive-sparse-training}} | |
| }} | |
| ``` | |
| ## Acknowledgments | |
| Trained using the `adaptive-sparse-training` package. Special thanks to the PyTorch and HuggingFace communities. | |
| --- | |
| *This model card was auto-generated by the AST Training Dashboard.* | |
| """ | |
| # Initialize dashboard | |
| dashboard = ASTDashboard() | |
| # Gradio Interface | |
| def create_demo(): | |
| """Create Gradio demo interface""" | |
| with gr.Blocks(title="AST Training Dashboard") as demo: | |
| gr.Markdown(""" | |
| # β‘ Adaptive Sparse Training Dashboard | |
| Train models with **60-70% less energy** while maintaining accuracy! | |
| This demo trains a model on CIFAR-10 using AST and generates a HuggingFace model card. | |
| """) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| gr.Markdown("### βοΈ Configuration") | |
| model_name = gr.Dropdown( | |
| choices=["resnet18", "efficientnet_b0", "mobilenetv3_small_100"], | |
| value="resnet18", | |
| label="Model Architecture" | |
| ) | |
| dataset = gr.Dropdown( | |
| choices=["cifar10"], | |
| value="cifar10", | |
| label="Dataset" | |
| ) | |
| activation_rate = gr.Slider( | |
| minimum=0.2, | |
| maximum=0.8, | |
| value=0.35, | |
| step=0.05, | |
| label="Target Activation Rate (lower = more savings)" | |
| ) | |
| gr.Markdown(f"**Energy Savings:** ~{(1-0.35)*100:.0f}%") | |
| epochs = gr.Slider( | |
| minimum=5, | |
| maximum=50, | |
| value=10, | |
| step=5, | |
| label="Training Epochs" | |
| ) | |
| train_btn = gr.Button("π Start Training", variant="primary", size="lg") | |
| with gr.Column(scale=2): | |
| gr.Markdown("### π Live Training Metrics") | |
| status = gr.Markdown("*Ready to train...*") | |
| plot = gr.Plot() | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("### π Generated Model Card") | |
| model_card = gr.Textbox( | |
| label="HuggingFace Model Card (Markdown)", | |
| lines=20, | |
| max_lines=30, | |
| ) | |
| gr.Markdown(""" | |
| **Next Steps:** | |
| 1. Copy the model card above | |
| 2. Create a new model on [HuggingFace Hub](https://huggingface.co/new) | |
| 3. Paste the model card into `README.md` | |
| 4. Upload your trained model weights | |
| """) | |
| # Training logic | |
| train_btn.click( | |
| fn=dashboard.start_training, | |
| inputs=[model_name, dataset, activation_rate, epochs], | |
| outputs=[status, plot, model_card], | |
| ) | |
| gr.Markdown(""" | |
| --- | |
| ## π Learn More | |
| - π¦ [PyPI Package](https://pypi.org/project/adaptive-sparse-training/) | |
| - π [GitHub Repo](https://github.com/oluwafemidiakhoa/adaptive-sparse-training) | |
| - π [Documentation](https://github.com/oluwafemidiakhoa/adaptive-sparse-training#readme) | |
| **Made with β€οΈ using Adaptive Sparse Training** | |
| """) | |
| return demo | |
| if __name__ == "__main__": | |
| demo = create_demo() | |
| demo.launch() | |