diff --git a/README.md b/README.md index 4b79a65e3b0..e5f27e8533b 100644 --- a/README.md +++ b/README.md @@ -53,96 +53,59 @@ limitations under the License. ## Overview -SparseML is a toolkit that includes APIs, CLIs, scripts and libraries that apply state-of-the-art [sparsification](https://docs.neuralmagic.com/user-guides/sparsification) algorithms such as pruning and quantization to any neural network. -General, recipe-driven approaches built around these algorithms enable the simplification of creating faster and smaller models for the ML performance community at large. +SparseML is an open-source model optimization toolkit that enables you to create inference-optimized sparse models using pruning, quantization, and distillation algorithms. Models optimized with SparseML can then be exported to the ONNX and deployed with [DeepSparse](https://github.com/neuralmagic/deepsparse/) for GPU-class performance on CPU hardware. -The [GitHub repository](https://github.com/neuralmagic/sparseml) contains integrations within the PyTorch, Keras, and TensorFlow V1 ecosystems, allowing for seamless model sparsification. +
+ +
+ +## Workflows - +SparseML enables you to create a sparse model trained on your dataset in two ways: +- **Sparse Transfer Learning** enables you to fine-tune a pre-sparsified model from [SparseZoo](https://sparsezoo.neuralmagic.com/) (an open-source repository of sparse models such as BERT, YOLOv5, and ResNet-50) onto your dataset, while maintaining sparsity. This pathway works just like typical fine-tuning you are used to in training CV and NLP models, and is strongly preferred for if your model architecture is availble in SparseZoo. -## Highlights +- **Sparsification from Scratch** enables you to apply state-of-the-art pruning (like gradual magnitude pruning or OBS pruning) and quantization (like quantization aware training) algorithms to arbitrary PyTorch and Hugging Face models. This pathway requires more experimentation, but allows you to create a sparse version of any model. -### Integrations +## Integrations - -### Creating Sparse Models - - -### Transfer Learning from Sparse Models - - - - ## Tutorials -### 🖼️ Computer Vision - -- [Sparsifying PyTorch Models Using Recipes](https://github.com/neuralmagic/sparseml/blob/main/integrations/pytorch/tutorials/sparsifying_pytorch_models_using_recipes.md) -- [Sparsifying YOLOv3 Using Recipes](https://github.com/neuralmagic/sparseml/blob/main/integrations/ultralytics-yolov3/tutorials/sparsifying_yolov3_using_recipes.md) -- [Sparsifying YOLOv5 Using Recipes](https://github.com/neuralmagic/sparseml/blob/main/integrations/ultralytics-yolov5/tutorials/sparsifying_yolov5_using_recipes.md) -- [Sparsifying YOLACT Using Recipes](https://github.com/neuralmagic/sparseml/blob/main/integrations/dbolya-yolact/tutorials/sparsifying_yolact_using_recipes.md) -- [Sparse Transfer Learning for Image Classification](https://github.com/neuralmagic/sparseml/blob/main/integrations/pytorch/tutorials/classification_sparse_transfer_learning_tutorial.md) -- [Sparse Transfer Learning With YOLOv3](https://github.com/neuralmagic/sparseml/blob/main/integrations/ultralytics-yolov3/tutorials/yolov3_sparse_transfer_learning.md) -- [Sparse Transfer Learning With YOLOv5](https://github.com/neuralmagic/sparseml/blob/main/integrations/ultralytics-yolov5/tutorials/yolov5_sparse_transfer_learning.md) +### PyTorch +- [Sparse Transfer Learning with the CLI](integrations/torchvision/tutorials/sparse-transfer-learning.md) +- [Sparse Transfer Learning with the Python API](integrations/torchvision/tutorials/docs-torchvision-python-transfer-imagenette.ipynb) +- [Sparsify From Scratch with the Python API](integrations/torchvision/tutorials/docs-torchvision-sparsify-from-scratch-resnet50-beans.ipynb) - **Notebooks** +### Hugging Face Transformers +- [Sparse Transfer Learning Overview with the Python API](integrations/huggingface-transformers/tutorials/sparse-transfer-learning-bert-python.md) +- [Sparse Transfer Learning Overview with the CLI](integrations/huggingface-transformers/tutorials/sparse-transfer-learning-bert.md) +- [Sparse Transfer Learning for Sentiment Analysis](integrations/huggingface-transformers/tutorials/sentiment-analysis/sentiment-analysis-cli.md), [for Text Classification](integrations/huggingface-transformers/tutorials/text-classification/text-classification-cli.md), [for Token Classification](integrations/huggingface-transformers/tutorials/token-classification/token-classification-cli.md), [for Question Answering](integrations/huggingface-transformers/tutorials/question-answering/question-answering-cli.md) -- [Keras Image Classification Model Pruning Using SparseML](https://github.com/neuralmagic/sparseml/blob/main/integrations/keras/notebooks/classification.ipynb) -- [PyTorch Image Classification Model Pruning Using SparseML](https://github.com/neuralmagic/sparseml/blob/main/integrations/pytorch/notebooks/classification.ipynb) -- [PyTorch Image Detection Model Pruning Using SparseML](https://github.com/neuralmagic/sparseml/blob/main/integrations/pytorch/notebooks/detection.ipynb) -- [Sparse-Quantized Transfer Learning in PyTorch Using SparseML](https://github.com/neuralmagic/sparseml/blob/main/integrations/pytorch/notebooks/sparse_quantized_transfer_learning.ipynb) -- [Torchvision Classification Model Pruning Using SparseML](https://github.com/neuralmagic/sparseml/blob/main/integrations/pytorch/notebooks/torchvision.ipynb) -- [TensorFlow v1 Classification Model Pruning Using SparseML](https://github.com/neuralmagic/sparseml/blob/main/integrations/tensorflow_v1/notebooks/classification.ipynb) +### Ultralytics YOLOv5 +- [Sparse Transfer Learning with the CLI](integrations/ultralytics-yolov5/tutorials/sparse-transfer-learning.md) +- [Sparsify From Scatch with the CLI](integrations/ultralytics-yolov5/tutorials/sparsify-from-scratch.md) -### 📰 NLP -- [Sparsifying BERT Models Using Recipes](https://github.com/neuralmagic/sparseml/blob/main/integrations/huggingface-transformers/tutorials/sparsifying_bert_using_recipes.md) -- [Sparse Transfer Learning With BERT](https://github.com/neuralmagic/sparseml/blob/main/integrations/huggingface-transformers/tutorials/bert_sparse_transfer_learning.md) +### Links to Additional Examples +- [PyTorch](integrations/torchvision#tutorials) +- [Hugging Face Transformers](integrations/huggingface-transformers#tutorials) +- [Ultralytics YOLOv5](integrations/ultralytics-yolov5#tutorials) ## Installation This repository is tested on Python 3.7-3.10, and Linux/Debian systems. + It is recommended to install in a [virtual environment](https://docs.python.org/3/library/venv.html) to keep your system in order. Currently supported ML Frameworks are the following: `torch>=1.1.0,<=1.12.1`, `tensorflow>=1.8.0,<2.0.0`, `tensorflow.keras >= 2.2.0`. @@ -156,44 +119,59 @@ More information on installation such as optional dependencies and requirements ## Quick Tour -To enable flexibility, ease of use, and repeatability, sparsifying a model is done using a recipe. -The recipes encode the instructions needed for modifying the model and/or training process as a list of modifiers. -Example modifiers can be anything from setting the learning rate for the optimizer to gradual magnitude pruning. -The files are written in [YAML](https://yaml.org/) and stored in YAML or [markdown](https://www.markdownguide.org/) files using [YAML front matter.](https://assemble.io/docs/YAML-front-matter.html) The rest of the SparseML system is coded to parse the recipes into a native format for the desired framework and apply the modifications to the model and training pipeline. +### Recipes + +To enable flexibility, ease of use, and repeatability, SparseML uses a declarative interface called `recipes` for specifying the sparsity-related algorithms and hyperparamters that should be applied by SparseML. -`ScheduledModifierManager` classes can be created from recipes in all supported ML frameworks. -The manager classes handle overriding the training graphs to apply the modifiers as described in the desired recipe. -Managers can apply recipes in one shot or training aware ways. -One shot is invoked by calling `.apply(...)` on the manager while training aware requires calls into `initialize(...)` (optional), `modify(...)`, and `finalize(...)`. +`Recipes` are YAML-files formatted as a list of `modifiers`, which encode the instructions for SparseML. Example `modifiers` can be anything from setting the learning rate to encoding the hyperparameters of the gradual magnitude pruning algorithm. The SparseML system parses the `recipes` into a native format for each framework and applies the modifications to the model and training pipeline. + +### Python API + +Because of the declarative, recipe-based approach, you can add SparseML to your existing PyTorch traing pipelines. The `ScheduleModifierManager` class is responsible for parsing the YAML `recipes` and overriding standard PyTorch model and optimizer objects, encoding the logic of the sparsity algorithms from the recipe. Once you call `manager.modify`, you can then use the model and optimizer as usual, as SparseML abstracts away the complexity of the sparsification algorithms. + +The workflow looks like this: -For the frameworks, this means only a few lines of code need to be added to begin supporting pruning, quantization, and other modifications to most training pipelines. -For example, the following applies a recipe in a training aware manner: ```python -model = Model() # model definition -optimizer = Optimizer() # optimizer definition -train_data = TrainData() # train data definition -batch_size = BATCH_SIZE # training batch size +model = Model() # model definition +optimizer = Optimizer() # optimizer definition +train_data = TrainData() # train data definition +batch_size = BATCH_SIZE # training batch size steps_per_epoch = len(train_data) // batch_size from sparseml.pytorch.optim import ScheduledModifierManager manager = ScheduledModifierManager.from_yaml(PATH_TO_RECIPE) optimizer = manager.modify(model, optimizer, steps_per_epoch) -# PyTorch training code +# typical PyTorch training loop, using your model/optimizer as usual manager.finalize(model) ``` -Instead of training aware, the following example code shows how to execute a recipe in a one shot manner: -```python -model = Model() # model definition +- Check out the [PyTorch integration docs](integrations/torchvision) for full usage examples of the Python API. +- Check out the [Hugging Face integration docs](integrations/huggingface-transformers) for details of using SparseML with the Hugging Face `Trainer`. -from sparseml.pytorch.optim import ScheduledModifierManager -manager = ScheduledModifierManager.from_yaml(PATH_TO_RECIPE) -manager.apply(model) +### SparseML CLI + +In addition to the code-level API, SparseML offers pre-made training pipelines for common NLP and CV tasks via the CLI interface. The CLI enables you to kick-off training runs with various utilities like dataset loading and pre-processing, checkpoint saving, metric reporting, and logging handled for you. This makes it easy to get up and running in common training pathways. + +For instance, we can use the following to kick off a YOLOv5 sparse transfer learning run onto the VOC dataset (using SparseZoo stubs to pull down a sparse model checkpoint and transfer learning recipe): + +```bash +sparseml.yolov5.train \ + --weights zoo:cv/detection/yolov5-s/pytorch/ultralytics/coco/pruned75_quant-none?recipe_type=transfer_learn \ + --recipe zoo:cv/detection/yolov5-s/pytorch/ultralytics/coco/pruned75_quant-none?recipe_type=transfer_learn \ + --data VOC.yaml \ + --hyp hyps/hyp.finetune.yaml --cfg yolov5s.yaml --patience 0 ``` +- Check out the [YOLOv5 CLI example](ultralytics-yolov5/tutorials/sparse-transfer-learning.md) for more details on the YOLOv5 training pipeline +- Check out the [Hugging Face CLI example](integrations/huggingface-transformers/tutorials/sparse-transfer-learning-bert.md) for more details on the available NLP training pipelines +- Check out the [Torchvision CLI example](integrations/torchvision/tutorials/sparse-transfer-learning.md) for more details on the image classification training pipelines + +### Additional Resources + More information on the codebase and contained processes can be found in the SparseML docs: +- [Examples and Tutorials](integrations) - [Sparsification Code](https://docs.neuralmagic.com/get-started/sparsify-a-model) - [Sparsification Recipes](https://docs.neuralmagic.com/user-guides/recipes) - [Exporting to ONNX](https://docs.neuralmagic.com/user-guides/onnx-export) diff --git a/docs/images/sparseml-workflow.png b/docs/images/sparseml-workflow.png new file mode 100644 index 00000000000..f870b4e97c3 Binary files /dev/null and b/docs/images/sparseml-workflow.png differ diff --git a/integrations/huggingface-transformers/README.md b/integrations/huggingface-transformers/README.md index 137734fbe17..6b2c86c07a5 100644 --- a/integrations/huggingface-transformers/README.md +++ b/integrations/huggingface-transformers/README.md @@ -20,7 +20,6 @@ This directory explains how to use SparseML's `transformers` integration to trai There are two main workflows enabled by SparseML: - **Sparse Transfer Learning** - fine-tune a pre-sparsified checkpoint on your own dataset **[RECOMMENDED]** - - **Sparsification from Scratch** - apply pruning and quantization to sparsify `transformer` models from scratch Once trained, SparseML enables you to export models to the ONNX format, such that they can be deployed with DeepSparse. diff --git a/integrations/old-examples/README.md b/integrations/old-examples/README.md new file mode 100644 index 00000000000..25f69459dcf --- /dev/null +++ b/integrations/old-examples/README.md @@ -0,0 +1,20 @@ + + +# Examples + +This directory contains old examples of SparseML integrated with other libraries. Note that these pathways +have not been tested recently, but we have left there here as examples of how to integrate SparseML into a new repository. \ No newline at end of file diff --git a/integrations/dbolya-yolact/README.md b/integrations/old-examples/dbolya-yolact/README.md similarity index 100% rename from integrations/dbolya-yolact/README.md rename to integrations/old-examples/dbolya-yolact/README.md diff --git a/integrations/dbolya-yolact/recipes/yolact.pruned.md b/integrations/old-examples/dbolya-yolact/recipes/yolact.pruned.md similarity index 100% rename from integrations/dbolya-yolact/recipes/yolact.pruned.md rename to integrations/old-examples/dbolya-yolact/recipes/yolact.pruned.md diff --git a/integrations/dbolya-yolact/recipes/yolact.pruned_quant.md b/integrations/old-examples/dbolya-yolact/recipes/yolact.pruned_quant.md similarity index 100% rename from integrations/dbolya-yolact/recipes/yolact.pruned_quant.md rename to integrations/old-examples/dbolya-yolact/recipes/yolact.pruned_quant.md diff --git a/integrations/dbolya-yolact/recipes/yolact.quantized.md b/integrations/old-examples/dbolya-yolact/recipes/yolact.quantized.md similarity index 100% rename from integrations/dbolya-yolact/recipes/yolact.quantized.md rename to integrations/old-examples/dbolya-yolact/recipes/yolact.quantized.md diff --git a/integrations/dbolya-yolact/tutorials/sparsifying_yolact_using_recipes.md b/integrations/old-examples/dbolya-yolact/tutorials/sparsifying_yolact_using_recipes.md similarity index 100% rename from integrations/dbolya-yolact/tutorials/sparsifying_yolact_using_recipes.md rename to integrations/old-examples/dbolya-yolact/tutorials/sparsifying_yolact_using_recipes.md diff --git a/integrations/keras/README.md b/integrations/old-examples/keras/README.md similarity index 100% rename from integrations/keras/README.md rename to integrations/old-examples/keras/README.md diff --git a/integrations/keras/classification.py b/integrations/old-examples/keras/classification.py similarity index 100% rename from integrations/keras/classification.py rename to integrations/old-examples/keras/classification.py diff --git a/integrations/keras/notebooks/classification.ipynb b/integrations/old-examples/keras/notebooks/classification.ipynb similarity index 100% rename from integrations/keras/notebooks/classification.ipynb rename to integrations/old-examples/keras/notebooks/classification.ipynb diff --git a/integrations/keras/prune_resnet20.py b/integrations/old-examples/keras/prune_resnet20.py similarity index 100% rename from integrations/keras/prune_resnet20.py rename to integrations/old-examples/keras/prune_resnet20.py diff --git a/integrations/keras/recipes/.gitkeep b/integrations/old-examples/keras/recipes/.gitkeep similarity index 100% rename from integrations/keras/recipes/.gitkeep rename to integrations/old-examples/keras/recipes/.gitkeep diff --git a/integrations/keras/tutorials/.gitkeep b/integrations/old-examples/keras/tutorials/.gitkeep similarity index 100% rename from integrations/keras/tutorials/.gitkeep rename to integrations/old-examples/keras/tutorials/.gitkeep diff --git a/integrations/pytorch/README.md b/integrations/old-examples/pytorch/README.md similarity index 100% rename from integrations/pytorch/README.md rename to integrations/old-examples/pytorch/README.md diff --git a/integrations/pytorch/argparser_/nm_argparser_.py b/integrations/old-examples/pytorch/argparser_/nm_argparser_.py similarity index 100% rename from integrations/pytorch/argparser_/nm_argparser_.py rename to integrations/old-examples/pytorch/argparser_/nm_argparser_.py diff --git a/integrations/pytorch/argparser_/test_nmargparser.py b/integrations/old-examples/pytorch/argparser_/test_nmargparser.py similarity index 100% rename from integrations/pytorch/argparser_/test_nmargparser.py rename to integrations/old-examples/pytorch/argparser_/test_nmargparser.py diff --git a/integrations/pytorch/export.py b/integrations/old-examples/pytorch/export.py similarity index 100% rename from integrations/pytorch/export.py rename to integrations/old-examples/pytorch/export.py diff --git a/integrations/pytorch/lr_analysis.py b/integrations/old-examples/pytorch/lr_analysis.py similarity index 100% rename from integrations/pytorch/lr_analysis.py rename to integrations/old-examples/pytorch/lr_analysis.py diff --git a/integrations/pytorch/notebooks/classification.ipynb b/integrations/old-examples/pytorch/notebooks/classification.ipynb similarity index 100% rename from integrations/pytorch/notebooks/classification.ipynb rename to integrations/old-examples/pytorch/notebooks/classification.ipynb diff --git a/integrations/pytorch/notebooks/detection.ipynb b/integrations/old-examples/pytorch/notebooks/detection.ipynb similarity index 100% rename from integrations/pytorch/notebooks/detection.ipynb rename to integrations/old-examples/pytorch/notebooks/detection.ipynb diff --git a/integrations/pytorch/notebooks/sparse_quantized_transfer_learning.ipynb b/integrations/old-examples/pytorch/notebooks/sparse_quantized_transfer_learning.ipynb similarity index 100% rename from integrations/pytorch/notebooks/sparse_quantized_transfer_learning.ipynb rename to integrations/old-examples/pytorch/notebooks/sparse_quantized_transfer_learning.ipynb diff --git a/integrations/pytorch/notebooks/torchvision.ipynb b/integrations/old-examples/pytorch/notebooks/torchvision.ipynb similarity index 100% rename from integrations/pytorch/notebooks/torchvision.ipynb rename to integrations/old-examples/pytorch/notebooks/torchvision.ipynb diff --git a/integrations/pytorch/pr_sensitivity.py b/integrations/old-examples/pytorch/pr_sensitivity.py similarity index 100% rename from integrations/pytorch/pr_sensitivity.py rename to integrations/old-examples/pytorch/pr_sensitivity.py diff --git a/integrations/pytorch/recipes/.gitkeep b/integrations/old-examples/pytorch/recipes/.gitkeep similarity index 100% rename from integrations/pytorch/recipes/.gitkeep rename to integrations/old-examples/pytorch/recipes/.gitkeep diff --git a/integrations/pytorch/recipes/classification.transfer_learn_pruned.md b/integrations/old-examples/pytorch/recipes/classification.transfer_learn_pruned.md similarity index 100% rename from integrations/pytorch/recipes/classification.transfer_learn_pruned.md rename to integrations/old-examples/pytorch/recipes/classification.transfer_learn_pruned.md diff --git a/integrations/pytorch/recipes/classification.transfer_learn_pruned_quantized.md b/integrations/old-examples/pytorch/recipes/classification.transfer_learn_pruned_quantized.md similarity index 100% rename from integrations/pytorch/recipes/classification.transfer_learn_pruned_quantized.md rename to integrations/old-examples/pytorch/recipes/classification.transfer_learn_pruned_quantized.md diff --git a/integrations/pytorch/recipes/mobilenet-pruned.md b/integrations/old-examples/pytorch/recipes/mobilenet-pruned.md similarity index 100% rename from integrations/pytorch/recipes/mobilenet-pruned.md rename to integrations/old-examples/pytorch/recipes/mobilenet-pruned.md diff --git a/integrations/pytorch/recipes/mobilenet-pruned_quant.md b/integrations/old-examples/pytorch/recipes/mobilenet-pruned_quant.md similarity index 100% rename from integrations/pytorch/recipes/mobilenet-pruned_quant.md rename to integrations/old-examples/pytorch/recipes/mobilenet-pruned_quant.md diff --git a/integrations/pytorch/recipes/resnet50-imagenette-pruned.md b/integrations/old-examples/pytorch/recipes/resnet50-imagenette-pruned.md similarity index 100% rename from integrations/pytorch/recipes/resnet50-imagenette-pruned.md rename to integrations/old-examples/pytorch/recipes/resnet50-imagenette-pruned.md diff --git a/integrations/pytorch/recipes/resnet50-pruned.md b/integrations/old-examples/pytorch/recipes/resnet50-pruned.md similarity index 100% rename from integrations/pytorch/recipes/resnet50-pruned.md rename to integrations/old-examples/pytorch/recipes/resnet50-pruned.md diff --git a/integrations/pytorch/recipes/resnet50-pruned_quant-transfer_learn.md b/integrations/old-examples/pytorch/recipes/resnet50-pruned_quant-transfer_learn.md similarity index 100% rename from integrations/pytorch/recipes/resnet50-pruned_quant-transfer_learn.md rename to integrations/old-examples/pytorch/recipes/resnet50-pruned_quant-transfer_learn.md diff --git a/integrations/pytorch/recipes/resnet50-pruned_quant.md b/integrations/old-examples/pytorch/recipes/resnet50-pruned_quant.md similarity index 100% rename from integrations/pytorch/recipes/resnet50-pruned_quant.md rename to integrations/old-examples/pytorch/recipes/resnet50-pruned_quant.md diff --git a/integrations/pytorch/torchvision_sparsification.py b/integrations/old-examples/pytorch/torchvision_sparsification.py similarity index 100% rename from integrations/pytorch/torchvision_sparsification.py rename to integrations/old-examples/pytorch/torchvision_sparsification.py diff --git a/integrations/pytorch/train.py b/integrations/old-examples/pytorch/train.py similarity index 100% rename from integrations/pytorch/train.py rename to integrations/old-examples/pytorch/train.py diff --git a/integrations/pytorch/tutorials/.gitkeep b/integrations/old-examples/pytorch/tutorials/.gitkeep similarity index 100% rename from integrations/pytorch/tutorials/.gitkeep rename to integrations/old-examples/pytorch/tutorials/.gitkeep diff --git a/integrations/pytorch/tutorials/classification_sparse_transfer_learning_tutorial.md b/integrations/old-examples/pytorch/tutorials/classification_sparse_transfer_learning_tutorial.md similarity index 100% rename from integrations/pytorch/tutorials/classification_sparse_transfer_learning_tutorial.md rename to integrations/old-examples/pytorch/tutorials/classification_sparse_transfer_learning_tutorial.md diff --git a/integrations/pytorch/tutorials/sparsifying_pytorch_models_using_recipes.md b/integrations/old-examples/pytorch/tutorials/sparsifying_pytorch_models_using_recipes.md similarity index 100% rename from integrations/pytorch/tutorials/sparsifying_pytorch_models_using_recipes.md rename to integrations/old-examples/pytorch/tutorials/sparsifying_pytorch_models_using_recipes.md diff --git a/integrations/pytorch/utils.py b/integrations/old-examples/pytorch/utils.py similarity index 100% rename from integrations/pytorch/utils.py rename to integrations/old-examples/pytorch/utils.py diff --git a/integrations/pytorch/vision.py b/integrations/old-examples/pytorch/vision.py similarity index 100% rename from integrations/pytorch/vision.py rename to integrations/old-examples/pytorch/vision.py diff --git a/integrations/rwightman-timm/README.md b/integrations/old-examples/rwightman-timm/README.md similarity index 100% rename from integrations/rwightman-timm/README.md rename to integrations/old-examples/rwightman-timm/README.md diff --git a/integrations/rwightman-timm/recipes/vit_base.85.recal.config.yaml b/integrations/old-examples/rwightman-timm/recipes/vit_base.85.recal.config.yaml similarity index 100% rename from integrations/rwightman-timm/recipes/vit_base.85.recal.config.yaml rename to integrations/old-examples/rwightman-timm/recipes/vit_base.85.recal.config.yaml diff --git a/integrations/rwightman-timm/setup_integration.sh b/integrations/old-examples/rwightman-timm/setup_integration.sh similarity index 100% rename from integrations/rwightman-timm/setup_integration.sh rename to integrations/old-examples/rwightman-timm/setup_integration.sh diff --git a/integrations/tensorflow_v1/README.md b/integrations/old-examples/tensorflow_v1/README.md similarity index 100% rename from integrations/tensorflow_v1/README.md rename to integrations/old-examples/tensorflow_v1/README.md diff --git a/integrations/tensorflow_v1/classification.py b/integrations/old-examples/tensorflow_v1/classification.py similarity index 100% rename from integrations/tensorflow_v1/classification.py rename to integrations/old-examples/tensorflow_v1/classification.py diff --git a/integrations/tensorflow_v1/notebooks/classification.ipynb b/integrations/old-examples/tensorflow_v1/notebooks/classification.ipynb similarity index 100% rename from integrations/tensorflow_v1/notebooks/classification.ipynb rename to integrations/old-examples/tensorflow_v1/notebooks/classification.ipynb diff --git a/integrations/tensorflow_v1/recipes/.gitkeep b/integrations/old-examples/tensorflow_v1/recipes/.gitkeep similarity index 100% rename from integrations/tensorflow_v1/recipes/.gitkeep rename to integrations/old-examples/tensorflow_v1/recipes/.gitkeep diff --git a/integrations/tensorflow_v1/tutorials/.gitkeep b/integrations/old-examples/tensorflow_v1/tutorials/.gitkeep similarity index 100% rename from integrations/tensorflow_v1/tutorials/.gitkeep rename to integrations/old-examples/tensorflow_v1/tutorials/.gitkeep diff --git a/integrations/ultralytics-yolov3/README.md b/integrations/old-examples/ultralytics-yolov3/README.md similarity index 100% rename from integrations/ultralytics-yolov3/README.md rename to integrations/old-examples/ultralytics-yolov3/README.md diff --git a/integrations/ultralytics-yolov3/data/hyp.pruned.yaml b/integrations/old-examples/ultralytics-yolov3/data/hyp.pruned.yaml similarity index 100% rename from integrations/ultralytics-yolov3/data/hyp.pruned.yaml rename to integrations/old-examples/ultralytics-yolov3/data/hyp.pruned.yaml diff --git a/integrations/ultralytics-yolov3/data/hyp.pruned_quantized.yaml b/integrations/old-examples/ultralytics-yolov3/data/hyp.pruned_quantized.yaml similarity index 100% rename from integrations/ultralytics-yolov3/data/hyp.pruned_quantized.yaml rename to integrations/old-examples/ultralytics-yolov3/data/hyp.pruned_quantized.yaml diff --git a/integrations/ultralytics-yolov3/models/yolov3-spp.lrelu.yaml b/integrations/old-examples/ultralytics-yolov3/models/yolov3-spp.lrelu.yaml similarity index 100% rename from integrations/ultralytics-yolov3/models/yolov3-spp.lrelu.yaml rename to integrations/old-examples/ultralytics-yolov3/models/yolov3-spp.lrelu.yaml diff --git a/integrations/ultralytics-yolov3/recipes/yolov3-spp.pruned.md b/integrations/old-examples/ultralytics-yolov3/recipes/yolov3-spp.pruned.md similarity index 100% rename from integrations/ultralytics-yolov3/recipes/yolov3-spp.pruned.md rename to integrations/old-examples/ultralytics-yolov3/recipes/yolov3-spp.pruned.md diff --git a/integrations/ultralytics-yolov3/recipes/yolov3-spp.pruned.short.md b/integrations/old-examples/ultralytics-yolov3/recipes/yolov3-spp.pruned.short.md similarity index 100% rename from integrations/ultralytics-yolov3/recipes/yolov3-spp.pruned.short.md rename to integrations/old-examples/ultralytics-yolov3/recipes/yolov3-spp.pruned.short.md diff --git a/integrations/ultralytics-yolov3/recipes/yolov3-spp.pruned_quantized.md b/integrations/old-examples/ultralytics-yolov3/recipes/yolov3-spp.pruned_quantized.md similarity index 100% rename from integrations/ultralytics-yolov3/recipes/yolov3-spp.pruned_quantized.md rename to integrations/old-examples/ultralytics-yolov3/recipes/yolov3-spp.pruned_quantized.md diff --git a/integrations/ultralytics-yolov3/recipes/yolov3-spp.pruned_quantized.short.md b/integrations/old-examples/ultralytics-yolov3/recipes/yolov3-spp.pruned_quantized.short.md similarity index 100% rename from integrations/ultralytics-yolov3/recipes/yolov3-spp.pruned_quantized.short.md rename to integrations/old-examples/ultralytics-yolov3/recipes/yolov3-spp.pruned_quantized.short.md diff --git a/integrations/ultralytics-yolov3/recipes/yolov3-spp.test.md b/integrations/old-examples/ultralytics-yolov3/recipes/yolov3-spp.test.md similarity index 100% rename from integrations/ultralytics-yolov3/recipes/yolov3-spp.test.md rename to integrations/old-examples/ultralytics-yolov3/recipes/yolov3-spp.test.md diff --git a/integrations/ultralytics-yolov3/recipes/yolov3-spp.transfer_learn_pruned.md b/integrations/old-examples/ultralytics-yolov3/recipes/yolov3-spp.transfer_learn_pruned.md similarity index 100% rename from integrations/ultralytics-yolov3/recipes/yolov3-spp.transfer_learn_pruned.md rename to integrations/old-examples/ultralytics-yolov3/recipes/yolov3-spp.transfer_learn_pruned.md diff --git a/integrations/ultralytics-yolov3/recipes/yolov3-spp.transfer_learn_pruned_quantized.md b/integrations/old-examples/ultralytics-yolov3/recipes/yolov3-spp.transfer_learn_pruned_quantized.md similarity index 100% rename from integrations/ultralytics-yolov3/recipes/yolov3-spp.transfer_learn_pruned_quantized.md rename to integrations/old-examples/ultralytics-yolov3/recipes/yolov3-spp.transfer_learn_pruned_quantized.md diff --git a/integrations/ultralytics-yolov3/setup_integration.sh b/integrations/old-examples/ultralytics-yolov3/setup_integration.sh similarity index 100% rename from integrations/ultralytics-yolov3/setup_integration.sh rename to integrations/old-examples/ultralytics-yolov3/setup_integration.sh diff --git a/integrations/ultralytics-yolov3/tutorials/images/pruned-quantized-result.jpeg b/integrations/old-examples/ultralytics-yolov3/tutorials/images/pruned-quantized-result.jpeg similarity index 100% rename from integrations/ultralytics-yolov3/tutorials/images/pruned-quantized-result.jpeg rename to integrations/old-examples/ultralytics-yolov3/tutorials/images/pruned-quantized-result.jpeg diff --git a/integrations/ultralytics-yolov3/tutorials/images/pruned-quantized-wandb-chart.png b/integrations/old-examples/ultralytics-yolov3/tutorials/images/pruned-quantized-wandb-chart.png similarity index 100% rename from integrations/ultralytics-yolov3/tutorials/images/pruned-quantized-wandb-chart.png rename to integrations/old-examples/ultralytics-yolov3/tutorials/images/pruned-quantized-wandb-chart.png diff --git a/integrations/ultralytics-yolov3/tutorials/images/transfer-learning-wandb-chart.png b/integrations/old-examples/ultralytics-yolov3/tutorials/images/transfer-learning-wandb-chart.png similarity index 100% rename from integrations/ultralytics-yolov3/tutorials/images/transfer-learning-wandb-chart.png rename to integrations/old-examples/ultralytics-yolov3/tutorials/images/transfer-learning-wandb-chart.png diff --git a/integrations/ultralytics-yolov3/tutorials/sparsifying_yolov3_using_recipes.md b/integrations/old-examples/ultralytics-yolov3/tutorials/sparsifying_yolov3_using_recipes.md similarity index 100% rename from integrations/ultralytics-yolov3/tutorials/sparsifying_yolov3_using_recipes.md rename to integrations/old-examples/ultralytics-yolov3/tutorials/sparsifying_yolov3_using_recipes.md diff --git a/integrations/ultralytics-yolov3/tutorials/yolov3_sparse_transfer_learning.md b/integrations/old-examples/ultralytics-yolov3/tutorials/yolov3_sparse_transfer_learning.md similarity index 100% rename from integrations/ultralytics-yolov3/tutorials/yolov3_sparse_transfer_learning.md rename to integrations/old-examples/ultralytics-yolov3/tutorials/yolov3_sparse_transfer_learning.md diff --git a/integrations/torchvision/README.md b/integrations/torchvision/README.md new file mode 100644 index 00000000000..241a7a8ff03 --- /dev/null +++ b/integrations/torchvision/README.md @@ -0,0 +1,212 @@ + + +# SparseML Torchvision Integration + +This directory explains how to use SparseML's `torchvision` integration to train inference-optimized sparse image classification models on your dataset. + +There are two main workflows enabled by SparseML: + +- **Sparse Transfer Learning** - fine-tune a pre-sparsified checkpoint on your own dataset **[RECOMMENDED]** +- **Sparsification from Scratch** - apply pruning and quantization to sparsify `torchvision` models from scratch + +Once trained, SparseML enables you to export models to the ONNX format, such that they can be deployed with DeepSparse. + +## Installation + +Install with `pip`: + +```bash +pip install sparseml[torchvision] +``` + +## Tutorials + +- [Sparse Transfer Learning with the CLI - ResNet-50](tutorials/sparse-transfer-learning.md) +- [Sparse Transfer Learning with the Python API - ResNet-50](tutorials/docs-torchvision-python-transfer-imagenette.ipynb) +- [Sparsification from Scratch with the Python API - ResNet-50](tutorials/docs-torchvision-sparsify-from-scratch-resnet50-beans.ipynb) +- [Sparsification from Scratch with the Python API - MobileNetv2](tutorials/docs-torchvision-sparsify-from-scratch-mobilenetv2-beans.ipynb) + +## Quick Tour + +### SparseZoo + +Neural Magic has pre-sparsified versions of common Torchvision models such as ResNet-50. These models can be deployed directly or can be fine-tuned onto custom dataset via sparse transfer learning. This makes it easy to create a sparse image classification model trained on your dataset. + +[Check out the available models](https://sparsezoo.neuralmagic.com/?domain=cv&sub_domain=classification&page=1) + +### Recipes + +Recipes are YAML files that encode the instructions for sparsifying a model or sparse transfer learning. SparseML accepts the recipes as inputs, parses the instructions, and applies the specified algorithms and hyperparameters during the training process. + +In such a way, recipes are the declarative interface for specifying which sparsity-related algorithms to apply. + +### SparseML Python API + +Because of the declarative, recipe-based approach, you can add SparseML to your PyTorch training pipelines with just a couple lines of code. + +SparseML's `ScheduleModifierManager` class is responsible for parsing the YAML recipes and overriding the standard PyTorch model and optimizer objects, +encoding the logic of the sparsity algorithms from the recipe. Once you call `manager.modify`, you can then use the model and optimizer as usual, as SparseML abstracts away the complexity of the sparsification algorithms. + +The workflow looks like this: + +```python +# typical model, optimizer, dataset definition +model = Model() +optimizer = Optimizer() +train_data = TrainData() + +# parse recipe + edit model/optimizer with sparsity-logic +from sparseml.pytorch.optim import ScheduledModifierManager +manager = ScheduledModifierManager.from_yaml(PATH_TO_RECIPE) +optimizer = manager.modify(model, optimizer, len(train_data)) + +# PyTorch training loop, using the model/optimizer as usual + +# clean-up +manager.finalize(model) +``` + +Note that the `model`, `optimizer`, and `dataset` are all standard PyTorch objects. We simply pass a recipe to the SparseML `SchedulerModifierManager` and SparseML handles the rest! + +### SparseML CLI + +In addition to the code-level API, SparseML offers pre-made training pipelines for image classification via the CLI interface. + +The CLI enables you to kick-off training runs with various utilities like dataset loading and pre-processing, checkpoint saving, metric reporting, and logging handled for you. + +To get started, we just need to a couple key arguments: +```bash +sparseml.image_classification.train \ + --checkpoint-path [CHECKPOINT-PATH] \ + --recipe [RECIPE-PATH] \ + --dataset-path [DATASET-PATH] +``` + +- `--checkpoint-path` specifies the starting model to use in the training process. It can either be a local path to a PyTorch checkpoint or a SparseZoo stub (which SparseML uses to download a PyTorch checkpoint). + +- `--dataset-path` specifies the dataset used for training. It must be a local path to a dataset in the ImageNet format (see CLI tutorials for more details). + +- `--recipe` specifies the sparsity related parameters of the training process. It can either be a local path to a YAML recipe file or a SparseZoo stub (which SparseML uses to download a YAML recipe file). The `recipe` is the key to enabling the sparsity-related algorithms implemented by SparseML (see the CLI tutorials for more details on recipes). + +For full usage, run: +```bash +sparseml.image_classification --help +``` + +## Quick Start: Sparse Transfer Learning with the CLI + +### Sparse Transfer Learning Overview + +Sparse Transfer is quite similiar to the typical transfer learning process used to train image classification models, where we fine-tune a checkpoint pretrained on ImageNet onto a smaller downstream dataset. With Sparse Transfer Learning, we simply start the fine-tuning process from a pre-sparsified checkpoint and maintain sparsity while the training process occurs. + +In this example, we will fine-tune a 95% pruned version of ResNet-50 ([available in SparseZoo](https://sparsezoo.neuralmagic.com/models/cv%2Fclassification%2Fresnet_v1-50%2Fpytorch%2Fsparseml%2Fimagenet%2Fpruned95_quant-none)) onto ImageNette. + +### Kick off Training + +We will use SparseML's `sparseml.torchvision.train` training script. + +#### Sparse Transfer Recipe + +To run sparse transfer learning, we first need to create/select a sparsification recipe. For sparse transfer, we need a recipe that instructs SparseML to maintain sparsity during training and to quantize the model. + +For the Imagenette dataset, there is a transfer learning recipe available in SparseZoo, identified by the following SparseZoo stub: +``` +zoo:cv/classification/resnet_v1-50/pytorch/sparseml/imagenet/pruned95_quant-none?recipe_type=transfer-classification +``` + +Here is what the recipe looks like: + +```yaml +# Epoch and Learning-Rate variables +num_epochs: 10.0 +init_lr: 0.0005 + +# quantization variables +quantization_epochs: 6.0 + +training_modifiers: + - !EpochRangeModifier + start_epoch: 0.0 + end_epoch: eval(num_epochs) + + - !LearningRateFunctionModifier + final_lr: 0.0 + init_lr: eval(init_lr) + lr_func: cosine + start_epoch: 0.0 + end_epoch: eval(num_epochs) + +# Phase 1 Sparse Transfer Learning / Recovery +sparse_transfer_learning_modifiers: + - !ConstantPruningModifier + start_epoch: 0.0 + params: __ALL_PRUNABLE__ + +# Phase 2 Apply quantization +sparse_quantized_transfer_learning_modifiers: + - !QuantizationModifier + start_epoch: eval(num_epochs - quantization_epochs) +``` + +The key `Modifiers` for sparse transfer learning are the following: +- `ConstantPruningModifier` instructs SparseML to maintain the sparsity structure of the network during the fine-tuning process +- `QuantizationModifier` instructs SparseML to apply quantization aware training to quantize the weights over the final epochs + +SparseML parses the `Modifers` in the recipe and updates the training loop with logic encoded therein. + +#### Download Dataset + +Download and unzip the Imagenette dataset: + +```bash +wget https://s3.amazonaws.com/fast-ai-imageclas/imagenette2-320.tgz +tar -xvf imagenette2-320.tgz +``` + +#### Run the Training Script + +Run the following to transfer learn from the 95% pruned-quantized ResNet-50 +onto ImageNette: +```bash +sparseml.image_classification.train \ + --recipe zoo:cv/classification/resnet_v1-50/pytorch/sparseml/imagenet/pruned95_quant-none?recipe_type=transfer-classification \ + --checkpoint-path zoo:cv/classification/resnet_v1-50/pytorch/sparseml/imagenet/pruned95_quant-none?recipe_type=transfer-classification \ + --arch-key resnet50 \ + --dataset-path ./imagenette2-320 \ + --batch-size 32 +``` + +The script uses the SparseZoo stubs to identify and download the starting checkpoint and YAML-based recipe file from the SparseZoo. SparseML parses the transfer learning recipe and adjusts the training logic to maintain sparsity during the fine-tuning process. + +The resulting model is 95% pruned and quantized and is trained on ImageNette! + +To transfer learn this sparsified model to other datasets you may have to adjust certain hyperparameters in this recipe and/or training script such as the optimizer type, the number of epochs, and the learning rates. + +### Export to ONNX + +The SparseML installation provides a `sparseml.image_classification.export_onnx` command that you can use to export the model to ONNX. Be sure the `--checkpoint_path` argument points to your trained model: + +```bash +sparseml.image_classification.export_onnx \ + --arch_key resnet50 \ + --checkpoint_path ./checkpoint.pth \ + --dataset-path ./imagenette2-320 +``` + +### Deploy with DeepSparse + +Once exported to ONNX, you can deploy your models with DeepSparse. Checkout the DeepSparse repo for examples. diff --git a/integrations/torchvision/tutorials/docs-torchvision-python-transfer-imagenette.ipynb b/integrations/torchvision/tutorials/docs-torchvision-python-transfer-imagenette.ipynb new file mode 100644 index 00000000000..69cc1f0138d --- /dev/null +++ b/integrations/torchvision/tutorials/docs-torchvision-python-transfer-imagenette.ipynb @@ -0,0 +1,7676 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "k39CzQqsOeQE" + }, + "source": [ + "# **Image Classification: Sparse Transfer Learning with the Python API**\n", + "\n", + "In this example, you will fine-tune a 95% pruned-quantized ResNet-50 model onto the Imagenette dataset using SparseML's Torchvision Integration.\n", + "\n", + "### **Sparse Transfer Learning Overview**\n", + "\n", + "Sparse Transfer Learning is very similiar to typical fine-tuning you are used to when training models. However, with Sparse Transfer Learning, we start the training process from a pre-sparsified checkpoint and maintain the sparsity structure while the fine tuning occurs. \n", + "\n", + "At the end, you will have a sparse model trained on your dataset, ready to be deployed with DeepSparse for GPU-class performance on CPUs!\n", + "\n", + "### **Pre-Sparsified Image Classification Model**\n", + "SparseZoo, Neural Magic's open source repository of pre-sparsified models, contains several families of image classification models including ResNet, MobileNet, and EfficientNet.\n", + "\n", + "In this case, we start the training process from a 95% pruned-quantized [ResNet-50 model](https://sparsezoo.neuralmagic.com/models/cv%2Fclassification%2Fresnet_v1-50%2Fpytorch%2Fsparseml%2Fimagenet%2Fpruned95_quant-none), which is identified by the following SparseZoo stub:\n", + "\n", + "```bash\n", + "zoo:cv/classification/resnet_v1-50/pytorch/sparseml/imagenet/pruned95_quant-none\n", + "```\n", + "\n", + "\n", + "**Let's dive in!**" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Y0WybTbssU0g" + }, + "source": [ + "## **Installation**\n", + "\n", + "Install SparseML via `pip`.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "OCGA94en19CF" + }, + "outputs": [], + "source": [ + "!pip install sparseml[torch,torchvision]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "OWXoz-YnPR8Z" + }, + "source": [ + "If you are running on Google Colab, restart the runtime after this step." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "H5DZiJrH3DiO" + }, + "outputs": [], + "source": [ + "import sparseml\n", + "import sparsezoo\n", + "import torch\n", + "import torchvision\n", + "print(torch.__version__)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "th1dNZiY-U56" + }, + "source": [ + "## **Step 1: Download the Sparse Checkpoint from the SparseZoo**\n", + "\n", + "We can use a SparseZoo stub to identify the model we want to use. In this case, we will use the 95% pruned and quantized version, which retains 99% of the baseline accuracy of the dense model. \n", + "\n", + "[Checkout the model card on SparseZoo](https://sparsezoo.neuralmagic.com/models/cv%2Fclassification%2Fresnet_v1-50%2Fpytorch%2Fsparseml%2Fimagenet%2Fpruned95_quant-none)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "Wk_EC5ar3F0L" + }, + "outputs": [], + "source": [ + "from sparseml.pytorch.models import ModelRegistry\n", + "\n", + "ZOO_STUB = \"zoo:cv/classification/resnet_v1-50/pytorch/sparseml/imagenet/pruned95_quant-none?recipe_type=transfer-classification\"\n", + "\n", + "# SparseZoo stub to pre-trained sparse-quantized ResNet-50 for imagenet dataset\n", + "model = ModelRegistry.create(\n", + " key=\"resnet50\",\n", + " pretrained_path=ZOO_STUB,\n", + " pretrained_dataset=\"imagenette\",\n", + " num_classes=10,\n", + " ignore_error_tensors=[\"classifier.fc.weight\", \"classifier.fc.bias\"],\n", + ")\n", + "input_shape = ModelRegistry.input_shape(\"resnet50\")\n", + "input_size = input_shape[-1]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "oMIVY3hYAgI8" + }, + "source": [ + "## **Step 2: Setup The Dataset**\n", + "\n", + "Download the datasets. We will use Imagenette dataset for this example. Checkout the [PyTorch documentation](https://pytorch.org/tutorials/beginner/basics/data_tutorial.html) on Datasets and Dataloaders for more derails on how Datasets work." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "KZBaOzAe-fQj" + }, + "outputs": [], + "source": [ + "from sparseml.pytorch.datasets import ImagenetteDataset, ImagenetteSize\n", + "\n", + "# Define your train and validation datasets below, here we will use Imagenette\n", + "print(\"\\nloading train dataset...\")\n", + "train_dataset = ImagenetteDataset(\n", + " train=True, dataset_size=ImagenetteSize.s320, image_size=input_size\n", + ")\n", + "\n", + "print(\"\\nloading val dataset...\")\n", + "val_dataset = ImagenetteDataset(\n", + " train=False, dataset_size=ImagenetteSize.s320, image_size=input_size\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "AA-J71G1_c_H" + }, + "source": [ + "## **Step 3: Setup Training Loop and Objects**\n", + "\n", + "This training loop is all native PyTorch, there is nothing SparseML related." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "QX9y0eBe4Bu4" + }, + "outputs": [], + "source": [ + "from tqdm.auto import tqdm\n", + "import math\n", + "\n", + "def run_model_one_epoch(model, data_loader, criterion, device, train=False, optimizer=None):\n", + " if train:\n", + " model.train()\n", + " else:\n", + " model.eval()\n", + "\n", + " running_loss = 0.0\n", + " total_correct = 0\n", + " total_predictions = 0\n", + "\n", + " # loop through batches\n", + " for step, (inputs, labels) in tqdm(enumerate(data_loader), total=len(data_loader)):\n", + " inputs = inputs.to(device)\n", + " labels = labels.to(device)\n", + "\n", + " if train:\n", + " optimizer.zero_grad()\n", + "\n", + " # compute loss, run backpropogation\n", + " outputs, _ = model(inputs) # model returns logits and softmax as a tuple\n", + " loss = criterion(outputs, labels)\n", + " if train:\n", + " loss.backward()\n", + " optimizer.step()\n", + "\n", + " running_loss += loss.item()\n", + "\n", + " # run evaluation\n", + " predictions = outputs.argmax(dim=1)\n", + " total_correct += torch.sum(predictions == labels).item()\n", + " total_predictions += inputs.size(0)\n", + "\n", + " # return loss and evaluation metric\n", + " loss = running_loss / (step + 1.0)\n", + " accuracy = total_correct / total_predictions\n", + " return loss, accuracy" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "GQL_dmO7QHQO" + }, + "source": [ + "Setup the dataloaders, loss, and optimizer. These are all native PyTorch, there is nothing SparseML related." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "In57pouf4P6r" + }, + "outputs": [], + "source": [ + "from torch.utils.data import DataLoader\n", + "from torch.nn import CrossEntropyLoss\n", + "from torch.optim import Adam\n", + "\n", + "# hyperparameters\n", + "BATCH_SIZE = 32\n", + "\n", + "# setup device\n", + "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n", + "model.to(device)\n", + "print(f\"Using device: {device}\")\n", + "\n", + "# setup data loaders\n", + "train_loader = DataLoader(\n", + " train_dataset, BATCH_SIZE, shuffle=True, pin_memory=True, num_workers=8\n", + ")\n", + "val_loader = DataLoader(\n", + " val_dataset, BATCH_SIZE, shuffle=False, pin_memory=True, num_workers=8\n", + ")\n", + "\n", + "# setup loss function and optimizer, LR will be overriden by sparseml\n", + "criterion = CrossEntropyLoss()\n", + "optimizer = Adam(model.parameters(), lr=8e-3)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "dUx2vnrrAwdX" + }, + "source": [ + "## **Step 5: Add Sparse Transfer Learning Logic with SparseML**\n", + "\n", + "First, we will download the use the SparseZoo `Model` class to download the transfer learning recipe to the local directory. You can also download directly from the SparseZoo website." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "PT_04J827o_a" + }, + "outputs": [], + "source": [ + "from sparsezoo import Model\n", + "\n", + "download_directory = \"./model_download_directory\"\n", + "zoo_model = Model(ZOO_STUB, download_path = download_directory)\n", + "recipe_path = zoo_model.recipes.default.path\n", + "print(recipe_path)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "KCMRFLFN8024" + }, + "source": [ + "#### **Inspecting the Recipe**\n", + "\n", + "Here is the transfer learning recipe:\n", + "\n", + "```yaml\n", + "# Epoch and Learning-Rate variables\n", + "num_epochs: 10.0\n", + "init_lr: 0.0005\n", + "\n", + "# quantization variables\n", + "quantization_epochs: 6.0\n", + "\n", + "training_modifiers:\n", + " - !EpochRangeModifier\n", + " start_epoch: 0.0\n", + " end_epoch: eval(num_epochs)\n", + "\n", + " - !LearningRateFunctionModifier\n", + " final_lr: 0.0\n", + " init_lr: eval(init_lr)\n", + " lr_func: cosine\n", + " start_epoch: 0.0\n", + " end_epoch: eval(num_epochs)\n", + "\n", + "# Phase 1 Sparse Transfer Learning / Recovery\n", + "sparse_transfer_learning_modifiers:\n", + " - !ConstantPruningModifier\n", + " start_epoch: 0.0\n", + " params: __ALL_PRUNABLE__\n", + "\n", + "# Phase 2 Apply quantization\n", + "sparse_quantized_transfer_learning_modifiers:\n", + " - !QuantizationModifier\n", + " start_epoch: eval(num_epochs - quantization_epochs)\n", + "```\n", + "\n", + "\n", + "The `Modifiers` in the transfer learning recipe are the important items that encode how SparseML should modify the training process for Sparse Transfer Learning:\n", + "- `ConstantPruningModifier` tells SparseML to pin weights at 0 over all epochs, maintaining the sparsity structure of the network\n", + "- `QuantizationModifier` tells SparseML to quanitze the weights with quantization aware training over the last 5 epochs\n", + "\n", + "\n", + "To transfer learn this sparsified model to other datasets you may have to adjust certain hyperparameters in this recipe and/or training script. Some considerations:\n", + "\n", + "- For more complex datasets, increase the number of epochs, adjusting the learning rate step accordingly\n", + "- Adding more learning rate step milestones can lead to more jumps in accuracy\n", + "- Increase the learning rate when increasing batch size\n", + "- Increase the number of epochs if using SGD instead of the Adam optimizer\n", + "- Update the base learning rate based on the number of steps needed to train your dataset " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "l5XhMbqb_7FM" + }, + "source": [ + "Next, we will use SparseML's `ScheduledModifierManager` to parse the instructions from the recipes and update the `optimizer` and `model` with the instructions encoded therein." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "xvbZ-avB4xdc" + }, + "outputs": [], + "source": [ + "from sparseml.pytorch.optim import ScheduledModifierManager\n", + "\n", + "# create ScheduledModifierManager and Optimizer wrapper\n", + "manager = ScheduledModifierManager.from_yaml(recipe_path)\n", + "optimizer = manager.modify(model, optimizer, steps_per_epoch=len(train_loader))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "nrgF_ur_B66y" + }, + "source": [ + "## **Step 6: Run Training**\n", + "\n", + "We pass the modified `model` and `optimizer` objects to the training loop we build above. Since we already called `manager.modify` all of the logic from the recipe is encoded in the `optimizer` and `model`. We can use the `model` and `optimizer`, and the SparseML system applies the algorithms specified in the recipe. In this case, since we applied a `ConstantPruningModifier`, the weights which are zero will be pinned to 0 during the fine-tuning, maintaining the sparsity structure as the model fine-tunes." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000, + "referenced_widgets": [ + "365d8cd0a55741b395ee0ba07f8404d0", + "4db683b764944e7abaac799b87856fc4", + "3ba4f091305f4ecba58e61a3ff7a41a3", + "24276cd8d882445fac4d59fc50465404", + "cba7023224ce4008a1a84d2e68c4b10b", + "33440a67dbe043589bf9e47dd8f06bc5", + "6b92eabd9cc14a41a5b8c06a95f2a461", + "6172621fe6474774a569e7f543d701c0", + "b3d716b99ede49b08da78dac38628125", + "75c7666da77744a185cdb21b810c9007", + "a72e0aec7ebc4f65a6e62f95f26b6e33", + "5719a6f214c946fc82b46274ee89ba63", + "fc625b9031b24690b10cc9408a678ae1", + "d0551e7bf98c4d56a667e8579b7a8394", + "5aaf8369f19346fb9ef6e83bee77706c", + "d61bc0378f9d4052b288557593fec4a7", + "ce525d1dc5734622b73c4e0864388f75", + "63ca01dc63d84bfd851c5a3c5bb39699", + "568155b1e8bd4b7f8fb99babbcb32acd", + "ab733440d25949a7a02f84d7ef2e75a4", + "c2c6fcdbd2364ecf97382dc9c7c14eba", + "b777873aaae545fea4cbc185254555fd", + "b44b6c0760ab4694a15032e717f8bd22", + "30dad6e494e145d3bee510e356dc0da2", + "bdb845bc132e4288af4e3bf6e4ce8f10", + "0806e9cc00a841319c29b526786d1e0b", + "711c3945a9764bff98e986c7b139c60d", + "ab446d1802304e10b0ac3e3b39abce14", + "74c2704c43574db6a1a101953126f0f6", + "fbd3bb63b7ac4b8cbcff584d49226930", + "fc6829f4240840ddb10ba194562a3127", + "2fd1adafaf374a9d9d06e113a19f0210", + "4edcabc454a54ebcb20d3777982909c1", + "5dd2b94a9e9f4eafaeb0e369fc960d7f", + "a6344a7197a54414804dd8d4a19430d2", + "93239cdb5ea046728cd5d952c5718ac1", + "fc12e0be1fbc45ac9d8e3a50cd58ed39", + "ab48f5c1c115446888fe6768385047b2", + "334551a828d04b33a0ed73d335c5744a", + "b9b61fe2bb92437ba81882aa4dad9c4a", + "1b0adead9311477c8901da39a85f506d", + "71874a3bc6734ce88ddff76ca042b409", + "e9b3bda8a95a40a7822961b84a39334c", + "178cc7579885416e8587d67b3e020989", + "fe703c6001554401a9e9f52836e6ba9d", + "63c7786ad23b49dd9328cf3101fca03b", + "f5d76345d11a4c3883f4bc728f1f7b67", + "22598c3d37684f848f0581fa105b5b23", + "7f51aa6075e14485bbb532b374247855", + "df73481b726c44d9944c8fa63287a60c", + "7d722aa2bfb34bcca0f8d3802bfddf11", + "74ea41607b834f30a75179017fe09ab4", + "82bc7f9ad69846248a6b6ea375274c7d", + "48a820915dea49cb836eee3559530b31", + "81231484ce764d7d8f08b835a60b6039", + "aa3099cb4a84476cabec49993e7e75ef", + "43098603cb834b11aacbe2123b394071", + "7cae68c449ad4b15ad5a95dff361745e", + "e41132385f42489ba1150213a4351adb", + "94a650bcbd80491081c1b500f9bdde31", + "977ff720f0dd40809f6c79fe472b735e", + "6cf087a2a16744a18200792194788ae2", + "c3f5281c0071455fbf4ddf888bc8a000", + "9d5e77107c4243d986c4ffd19f9b48af", + "c9d6790d51d04b26ac40e730c118828d", + "1141c0e0d2c041bb9e05253b49117b21", + "2b0e9f7c6a514215800184945cab6fe2", + "4711e077fd604ec7b36e05ddf4871b9f", + "cc3d0595159c49c8a54e3cda01bafb70", + "c569ca56532a48b0a51df650aabce06c", + "87e5e33c4a2346f6a5f208c473ba870b", + "fb7579ebc5124ee9b2de23f6dc2bba67", + "c8e8273720454cc2957f61626cac2034", + "f61fc34a0ee94f9bbc0a6c9bcfa06a2b", + "d115340a713445b59302c60387644de4", + "32a495107a5f4a8e8fe72e281f5ee47d", + "41f59e7f9fbe4fa29d7850192dbf02ff", + "bd1053c775aa48a29f2862a7130b38ee", + "3a5392e7c90c4a1ebd8b089d4eb10e42", + "774dffcb789e46c9bfa00da8f47de45d", + "7aeebaaf7f40434aa5cda9c8b560ecfa", + "22f6797e64db4fdf9eff9f32bb6d2d52", + "057b7575d2d04b66bdf7f27d1fb75646", + "c03fe86962434903a75be0ea95d2beeb", + "3cd3e98ef2364ad6be4711c9621e3404", + "9bb22293ff754067bbae1c0e006f630a", + "0168b617288942379053f80fcf791606", + "9d0ac0ec649f46abb5a635b524504c53", + "06661f1e1a85418986208cb5687a37ad", + "4eed5dbcb6064233a3dfa2fea2d2dd7a", + "cfbaf53d78fd4120b80821e9ebe1707b", + "a8b6874e76c7479882606013289b42dc", + "6752b91596a646ddbfef818ee63ab40b", + "fa65378678c74db7985eeecdc4ec2e8a", + "54e502b4ae214f2f8c45e35db5c8137a", + "b362ab5da06f4f74b5af3c4711e4d121", + "8992f1b1a84e41bbb3636aaaa8648d50", + "87637a6cdedf4ea19cc4eb4cb459ba5c", + "2927b8c2167f404d812b5fb6ca2cbe48", + "1d1a0ced3c2344d2a2b27a03db584bf2", + "d46754dfbb3e496190260e65022194b3", + "a08bb4188c50462385e59e8b42d5414d", + "2827004769d04d439b7290336ab4ce50", + "3ee2dd8e793945d0b68d7f590b0851b9", + "9cae0b373fea4e4e825bccf59bae9d8b", + "dcb55e706ca5439f99a3b199990b78a3", + "f214e772f12c4f3f8d05c906c6b57d3d", + "7c69e3e5fe1f4cba82a797ad8509c69d", + "78e85cb47f5d460ba5e6b14c6631abfc", + "ed591a7ff2f0403188f9f25f4465d80e", + "b0a8901bd1b04dd7b20edf84f377295c", + "55b4c5b37192419295bf4717290ef9dc", + "067c0b2648634d65971be53ac05c6ebd", + "6da1560e8fb749c29682bb95d838f7d4", + "11dae279dee54c289db7148b1ff31636", + "2ccda6a3615c4a20a9c6a7694e9e2d7e", + "50d255490e1e4ee08528d53ffec69a69", + "0fdbddf9af41499ab738707937eedcc3", + "84d9e268dc7e43bba8fb8ac3bdc2a3fb", + "5d9a2f9e66014beebfee3d1b399c9c80", + "e8b93f3076ad4f4e830fee1bb86443f9", + "5efa58b1a4d7404b9dcfc7e3da97dfb5", + "c63a966f6a104fd6b563809350f76ef0", + "7e1fee12c4274ddc9c8c9b107ec1bf03", + "8a6e60a408194cefb30e0c567e54c5b2", + "c8de4b3a67a14901a41b7ab5fcfef1d8", + "988554face9d422b9b9d7ec15b9f8f35", + "2b5905d64d094e249a200e554c944563", + "8fa4c37a95cc4c60a8254b6afc9ee3f7", + "958a2e10af3247d5a68baffc0fdbaf84", + "ee96aae30c844fbbac12f746244f974b", + "84a24649b3b245a9b8b76930939c0969", + "ccd0badc672f44c09ab50e18bfe58cee", + "446ce98237e74bceb7665c2e20ab3750", + "8099c4ca7a384d949bccbe314e98521a", + "7e2b65ad965549778444697f74e71f08", + "f450a00db3a54f9b8b49c1ad04177346", + "08a8deb25cc5455fad1a9b5f3b896c86", + "79a42c9cf3a940e7ab9ab6ed26a7ed93", + "b8fc39b9aed84495bc689704ef8526e6", + "f1825a71f6f64426b03e39c541f06136", + "d84d1932c9f847cf87c8ae3d9c77bec9", + "adb9fb37522343d9878d8f9d875c760b", + "69fe6cbcdace44dc883653a4c63491d6", + "67d702f1e5c74b1589ef017a98442ab4", + "53d13e52cb114d6ea781d7d10c9415fe", + "697fd62a7df44fbbbcd718a674e44c4a", + "7065b7f0ad194f6d90d5d7619ed60076", + "a2fe8be526b44a7bbe1da23e1ef95680", + "a3ada5d5c7b849e9afa0f1e2181967c3", + "276ad9db94064604bb9529cafd4076e8", + "fceeb818a6c24751aadf5b09c9dba435", + "b85e41d6779543df9857b56cf6677b0b", + "41f57141ef1f4aa78987a53175572d5b", + "7d2b868920f54a0c9f042c1f32018711", + "cabdd27082564769a84d309322faed41", + "aa03a9e03f73454cb2390208c4908a42", + "3eefe02dae684c1c9c008e54bee40417", + "93fc6e5c74b1499185237ea99264c66d", + "08e8ac31b1e74198b3b6ccdf956bebd7", + "6a3c09a0bef8461eb4f42c12f3fbf252", + "eba047c7a6b2457c8ea2046239f8e55c", + "21aa8ec04be2464295c755603f8bc2a4", + "c579b7c7d039483e8b8dcc033b3201d2", + "aa957a6c8e5e456990f1a2cd8a4e3762", + "9f4efda38b02479ab5148a7f1be85898", + "10c5f59cef0f43c88cda68a6e0a2448a", + "1645b680a4c4437d833c4e159b717468", + "c6893a93d0f04a86ade694b9e3c4b4c9", + "b4bd0a4cc8e049ca9a0071736e876ea4", + "e6282327f809437083bfd0288e701fef", + "aec2f6336d2b49aa8851e8c829b40a3f", + "a0631ef33079471c97476667c8fe5824", + "49992adb3d0e449e85f9fca905f3b929", + "77845f14cb3948c381d60fac9e11ea2e", + "17f07573df3f4697aa7d50e725fa9fe8", + "2c14f28492624d97a8fb80466f4e7691", + "e776baac3c13419d974722e1a4b36261", + "c54ee69a395a4a338660a0b3c3eb519f", + "8f1ab4f675be47d7a8949fbd44e559ee", + "bdba44b042924f5087b576248b8070e7", + "3755259c35754581a5fc228e90445edc", + "e26a18a5c5ad4bbcaba21c74cedb43be", + "3e081ee3984e45b8863dfca477fdc057", + "02bf462aafab42d5a282c6044f0924af", + "8d7738dd895a4c1898b1071ff71d0160", + "058c50a31d9b4520af109eedfc39c056", + "6765c1f60581479fa94407eb2e3085fb", + "133677d36e674c1893339c00f4c39170", + "a2834dd0211d430f84398e73740bd5bb", + "307c00f3dfc2480fac3d5e4e5be98742", + "729f331381b849d3a2774a914f25dec6", + "69021f9d497f480c818b7b41c26d1c75", + "504b506575ac41e5bf0d312f369c9321", + "cdce3ac597ea41f9a1b83d6372aba449", + "b442ab7d23cd414ca0e375bdad0e923c", + "f1309ee098df4c3897ed4cc7c4e54663", + "e34cb60c67a940b083d7d722cfe07b9e", + "8a094b4c0441477f8758f5ec8ea30fd9", + "f52365477a9d4f35aed9bf321bc91ce8", + "86ed55ca8f154b009d270be60533761e", + "6a07799a8784410884c71879e3cfd82c", + "53ca8bea715049f983c80cd510f6fe84", + "f6627cb15852455cae3d5ec169ff2062", + "f3f20217269545d4abdbbfae3f3bf08e", + "d58d868b0b714964885554ce7446d8c4", + "549d4f0df80f4040a5c183991e2fe9bb", + "400889d6caa448c880e1a21532409617", + "2d050f7835184b93b8d4f30dbd7cc16a", + "af29998c14de43dcb4e5d337ea1987d5", + "4f03e14b0a1d4a70a77a79c218822c33", + "19ae24edfd094eb3903f9a92c909a770", + "2c04efb851ee48f3b91423236614f256", + "321150e17ce0479385fc1dbfae365da4", + "ec630b4bb08b471f8c06057f9f030133", + "5be330fcf8c148eeaa7ff2c86c669714", + "23a6630e81c14ee7a79ae73501c38288", + "51b5216c2e2d44dea7d959d610e83da6", + "a615992bd57c4267932b7d4b103e33e8", + "ba4b8e385cb44a0489235aa4cf44a754" + ] + }, + "executionInfo": { + "elapsed": 1988739, + "status": "ok", + "timestamp": 1674842564679, + "user": { + "displayName": "Robert Shaw", + "userId": "07936720368498181527" + }, + "user_tz": 300 + }, + "id": "xy7JLoTM6RC_", + "outputId": "7f956859-081b-49fd-9723-e93a55e74c72" + }, + "outputs": [], + "source": [ + "# run transfer learning\n", + "epoch = manager.min_epochs\n", + "for epoch in range(manager.max_epochs):\n", + " # run training loop\n", + " epoch_name = f\"{epoch + 1}/{manager.max_epochs}\"\n", + " print(f\"Running Training Epoch {epoch_name}\")\n", + " train_loss, train_acc = run_model_one_epoch(\n", + " model, train_loader, criterion, device, train=True, optimizer=optimizer\n", + " )\n", + " print(\n", + " f\"Training Epoch: {epoch_name}\\nTraining Loss: {train_loss}\\nTop 1 Acc: {train_acc}\\n\"\n", + " )\n", + "\n", + " # run validation loop\n", + " print(f\"Running Validation Epoch {epoch_name}\")\n", + " val_loss, val_acc = run_model_one_epoch(model, val_loader, criterion, device)\n", + " print(\n", + " f\"Validation Epoch: {epoch_name}\\nVal Loss: {val_loss}\\nTop 1 Acc: {val_acc}\\n\"\n", + " )\n", + "\n", + "manager.finalize(model)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ZO9JUL6FD8kq" + }, + "source": [ + "We can see that the model is sparse. This command prints out the layerwise sparsity structure of the network." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 10, + "status": "ok", + "timestamp": 1674842564680, + "user": { + "displayName": "Robert Shaw", + "userId": "07936720368498181527" + }, + "user_tz": 300 + }, + "id": "1cHaXmcu4zGM", + "outputId": "426d92df-0aeb-4d61-8774-5f7ede0029b7" + }, + "outputs": [], + "source": [ + "from sparseml.pytorch.utils import get_prunable_layers, tensor_sparsity\n", + "\n", + "# print sparsities of each layer\n", + "for (name, layer) in get_prunable_layers(model):\n", + " print(f\"{name}.weight: {tensor_sparsity(layer.weight).item():.4f}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "WOSrElENDKcm" + }, + "source": [ + "## **Step 7: Export To ONNX**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "OJRVB-ZSDJ-6" + }, + "outputs": [], + "source": [ + "from sparseml.pytorch.utils import ModuleExporter\n", + "\n", + "save_dir = \"pytorch_classification\"\n", + "exporter = ModuleExporter(model, output_dir=save_dir)\n", + "exporter.export_pytorch(name=\"resnet50_imagenette_pruned.pth\")\n", + "exporter.export_onnx(torch.randn(1, 3, 224, 224), name=\"model.onnx\", convert_qat=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ffudiHTYDRC4" + }, + "source": [ + "## **Step 8: Run Inference with DeepSparse**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "5jqkTY3vFyG9" + }, + "outputs": [], + "source": [ + "!pip3 install deepsparse" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "AdUKQ-FNF66P" + }, + "outputs": [], + "source": [ + "from deepsparse import Pipeline\n", + "ic_pipeline = Pipeline.create(\n", + " \"image_classification\",\n", + " model_path=\"/content/pytorch_classification/model.onnx\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "l38TLFevKfpf" + }, + "source": [ + "Class 6 is `garbage_truck`" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 441, + "status": "ok", + "timestamp": 1674846828912, + "user": { + "displayName": "Robert Shaw", + "userId": "07936720368498181527" + }, + "user_tz": 300 + }, + "id": "eJv4S9fkGjdO", + "outputId": "df458b06-3ff4-4a0d-c1c2-3689799abaf5" + }, + "outputs": [], + "source": [ + "img_path = \"/root/.cache/nm_datasets/imagenette/imagenette-320/val/n03417042/ILSVRC2012_val_00001144.JPEG\" \n", + "images = [img_path]\n", + "print(ic_pipeline(images=images).labels[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 293 + }, + "executionInfo": { + "elapsed": 2, + "status": "ok", + "timestamp": 1674846829838, + "user": { + "displayName": "Robert Shaw", + "userId": "07936720368498181527" + }, + "user_tz": 300 + }, + "id": "79Xj9eqvJXaD", + "outputId": "2bdfbe4d-ab3c-4cc4-c54f-a6be6cbb2b2b" + }, + "outputs": [], + "source": [ + "from PIL import Image\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "\n", + "img = np.array(Image.open(img_path))\n", + "plt.matshow(img)" + ] + } + ], + "metadata": { + "accelerator": "GPU", + "colab": { + "authorship_tag": "ABX9TyM5OB17UuJsla11foDdM/QW", + "machine_shape": "hm", + "provenance": [] + }, + "gpuClass": "standard", + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.10" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "0168b617288942379053f80fcf791606": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "02bf462aafab42d5a282c6044f0924af": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "057b7575d2d04b66bdf7f27d1fb75646": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "058c50a31d9b4520af109eedfc39c056": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "06661f1e1a85418986208cb5687a37ad": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_4eed5dbcb6064233a3dfa2fea2d2dd7a", + "IPY_MODEL_cfbaf53d78fd4120b80821e9ebe1707b", + "IPY_MODEL_a8b6874e76c7479882606013289b42dc" + ], + "layout": "IPY_MODEL_6752b91596a646ddbfef818ee63ab40b" + } + }, + "067c0b2648634d65971be53ac05c6ebd": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_0fdbddf9af41499ab738707937eedcc3", + "max": 403, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_84d9e268dc7e43bba8fb8ac3bdc2a3fb", + "value": 403 + } + }, + "0806e9cc00a841319c29b526786d1e0b": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_2fd1adafaf374a9d9d06e113a19f0210", + "placeholder": "", + "style": "IPY_MODEL_4edcabc454a54ebcb20d3777982909c1", + "value": " 403/403 [02:15<00:00, 3.06it/s]" + } + }, + "08a8deb25cc5455fad1a9b5f3b896c86": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "08e8ac31b1e74198b3b6ccdf956bebd7": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "0fdbddf9af41499ab738707937eedcc3": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "10c5f59cef0f43c88cda68a6e0a2448a": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_e6282327f809437083bfd0288e701fef", + "placeholder": "", + "style": "IPY_MODEL_aec2f6336d2b49aa8851e8c829b40a3f", + "value": "100%" + } + }, + "1141c0e0d2c041bb9e05253b49117b21": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "11dae279dee54c289db7148b1ff31636": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "133677d36e674c1893339c00f4c39170": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_69021f9d497f480c818b7b41c26d1c75", + "placeholder": "", + "style": "IPY_MODEL_504b506575ac41e5bf0d312f369c9321", + "value": "100%" + } + }, + "1645b680a4c4437d833c4e159b717468": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_a0631ef33079471c97476667c8fe5824", + "max": 16, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_49992adb3d0e449e85f9fca905f3b929", + "value": 16 + } + }, + "178cc7579885416e8587d67b3e020989": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "17f07573df3f4697aa7d50e725fa9fe8": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "19ae24edfd094eb3903f9a92c909a770": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_23a6630e81c14ee7a79ae73501c38288", + "max": 16, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_51b5216c2e2d44dea7d959d610e83da6", + "value": 16 + } + }, + "1b0adead9311477c8901da39a85f506d": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "1d1a0ced3c2344d2a2b27a03db584bf2": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_d46754dfbb3e496190260e65022194b3", + "IPY_MODEL_a08bb4188c50462385e59e8b42d5414d", + "IPY_MODEL_2827004769d04d439b7290336ab4ce50" + ], + "layout": "IPY_MODEL_3ee2dd8e793945d0b68d7f590b0851b9" + } + }, + "21aa8ec04be2464295c755603f8bc2a4": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "22598c3d37684f848f0581fa105b5b23": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_48a820915dea49cb836eee3559530b31", + "placeholder": "", + "style": "IPY_MODEL_81231484ce764d7d8f08b835a60b6039", + "value": " 403/403 [02:15<00:00, 3.04it/s]" + } + }, + "22f6797e64db4fdf9eff9f32bb6d2d52": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "23a6630e81c14ee7a79ae73501c38288": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "24276cd8d882445fac4d59fc50465404": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_75c7666da77744a185cdb21b810c9007", + "placeholder": "", + "style": "IPY_MODEL_a72e0aec7ebc4f65a6e62f95f26b6e33", + "value": " 403/403 [02:08<00:00, 3.03it/s]" + } + }, + "276ad9db94064604bb9529cafd4076e8": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "2827004769d04d439b7290336ab4ce50": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_78e85cb47f5d460ba5e6b14c6631abfc", + "placeholder": "", + "style": "IPY_MODEL_ed591a7ff2f0403188f9f25f4465d80e", + "value": " 16/16 [00:04<00:00, 4.45it/s]" + } + }, + "2927b8c2167f404d812b5fb6ca2cbe48": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "2b0e9f7c6a514215800184945cab6fe2": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_4711e077fd604ec7b36e05ddf4871b9f", + "IPY_MODEL_cc3d0595159c49c8a54e3cda01bafb70", + "IPY_MODEL_c569ca56532a48b0a51df650aabce06c" + ], + "layout": "IPY_MODEL_87e5e33c4a2346f6a5f208c473ba870b" + } + }, + "2b5905d64d094e249a200e554c944563": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "2c04efb851ee48f3b91423236614f256": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_a615992bd57c4267932b7d4b103e33e8", + "placeholder": "", + "style": "IPY_MODEL_ba4b8e385cb44a0489235aa4cf44a754", + "value": " 16/16 [00:05<00:00, 4.37it/s]" + } + }, + "2c14f28492624d97a8fb80466f4e7691": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_e776baac3c13419d974722e1a4b36261", + "IPY_MODEL_c54ee69a395a4a338660a0b3c3eb519f", + "IPY_MODEL_8f1ab4f675be47d7a8949fbd44e559ee" + ], + "layout": "IPY_MODEL_bdba44b042924f5087b576248b8070e7" + } + }, + "2ccda6a3615c4a20a9c6a7694e9e2d7e": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "2d050f7835184b93b8d4f30dbd7cc16a": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "2fd1adafaf374a9d9d06e113a19f0210": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "307c00f3dfc2480fac3d5e4e5be98742": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_f1309ee098df4c3897ed4cc7c4e54663", + "placeholder": "", + "style": "IPY_MODEL_e34cb60c67a940b083d7d722cfe07b9e", + "value": " 16/16 [00:04<00:00, 4.46it/s]" + } + }, + "30dad6e494e145d3bee510e356dc0da2": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_ab446d1802304e10b0ac3e3b39abce14", + "placeholder": "", + "style": "IPY_MODEL_74c2704c43574db6a1a101953126f0f6", + "value": "100%" + } + }, + "321150e17ce0479385fc1dbfae365da4": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "32a495107a5f4a8e8fe72e281f5ee47d": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "33440a67dbe043589bf9e47dd8f06bc5": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "334551a828d04b33a0ed73d335c5744a": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "365d8cd0a55741b395ee0ba07f8404d0": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_4db683b764944e7abaac799b87856fc4", + "IPY_MODEL_3ba4f091305f4ecba58e61a3ff7a41a3", + "IPY_MODEL_24276cd8d882445fac4d59fc50465404" + ], + "layout": "IPY_MODEL_cba7023224ce4008a1a84d2e68c4b10b" + } + }, + "3755259c35754581a5fc228e90445edc": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "3a5392e7c90c4a1ebd8b089d4eb10e42": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_057b7575d2d04b66bdf7f27d1fb75646", + "placeholder": "", + "style": "IPY_MODEL_c03fe86962434903a75be0ea95d2beeb", + "value": "100%" + } + }, + "3ba4f091305f4ecba58e61a3ff7a41a3": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_6172621fe6474774a569e7f543d701c0", + "max": 403, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_b3d716b99ede49b08da78dac38628125", + "value": 403 + } + }, + "3cd3e98ef2364ad6be4711c9621e3404": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "3e081ee3984e45b8863dfca477fdc057": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "3ee2dd8e793945d0b68d7f590b0851b9": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "3eefe02dae684c1c9c008e54bee40417": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_c579b7c7d039483e8b8dcc033b3201d2", + "placeholder": "", + "style": "IPY_MODEL_aa957a6c8e5e456990f1a2cd8a4e3762", + "value": " 403/403 [03:54<00:00, 1.76it/s]" + } + }, + "400889d6caa448c880e1a21532409617": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "41f57141ef1f4aa78987a53175572d5b": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "41f59e7f9fbe4fa29d7850192dbf02ff": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "43098603cb834b11aacbe2123b394071": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_977ff720f0dd40809f6c79fe472b735e", + "placeholder": "", + "style": "IPY_MODEL_6cf087a2a16744a18200792194788ae2", + "value": "100%" + } + }, + "446ce98237e74bceb7665c2e20ab3750": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_08a8deb25cc5455fad1a9b5f3b896c86", + "placeholder": "", + "style": "IPY_MODEL_79a42c9cf3a940e7ab9ab6ed26a7ed93", + "value": "100%" + } + }, + "4711e077fd604ec7b36e05ddf4871b9f": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_fb7579ebc5124ee9b2de23f6dc2bba67", + "placeholder": "", + "style": "IPY_MODEL_c8e8273720454cc2957f61626cac2034", + "value": "100%" + } + }, + "48a820915dea49cb836eee3559530b31": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "49992adb3d0e449e85f9fca905f3b929": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "4db683b764944e7abaac799b87856fc4": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_33440a67dbe043589bf9e47dd8f06bc5", + "placeholder": "", + "style": "IPY_MODEL_6b92eabd9cc14a41a5b8c06a95f2a461", + "value": "100%" + } + }, + "4edcabc454a54ebcb20d3777982909c1": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "4eed5dbcb6064233a3dfa2fea2d2dd7a": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_fa65378678c74db7985eeecdc4ec2e8a", + "placeholder": "", + "style": "IPY_MODEL_54e502b4ae214f2f8c45e35db5c8137a", + "value": "100%" + } + }, + "4f03e14b0a1d4a70a77a79c218822c33": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_ec630b4bb08b471f8c06057f9f030133", + "placeholder": "", + "style": "IPY_MODEL_5be330fcf8c148eeaa7ff2c86c669714", + "value": "100%" + } + }, + "504b506575ac41e5bf0d312f369c9321": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "50d255490e1e4ee08528d53ffec69a69": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "51b5216c2e2d44dea7d959d610e83da6": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "53ca8bea715049f983c80cd510f6fe84": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "53d13e52cb114d6ea781d7d10c9415fe": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_276ad9db94064604bb9529cafd4076e8", + "max": 16, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_fceeb818a6c24751aadf5b09c9dba435", + "value": 16 + } + }, + "549d4f0df80f4040a5c183991e2fe9bb": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "54e502b4ae214f2f8c45e35db5c8137a": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "55b4c5b37192419295bf4717290ef9dc": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_2ccda6a3615c4a20a9c6a7694e9e2d7e", + "placeholder": "", + "style": "IPY_MODEL_50d255490e1e4ee08528d53ffec69a69", + "value": "100%" + } + }, + "568155b1e8bd4b7f8fb99babbcb32acd": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "5719a6f214c946fc82b46274ee89ba63": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_fc625b9031b24690b10cc9408a678ae1", + "IPY_MODEL_d0551e7bf98c4d56a667e8579b7a8394", + "IPY_MODEL_5aaf8369f19346fb9ef6e83bee77706c" + ], + "layout": "IPY_MODEL_d61bc0378f9d4052b288557593fec4a7" + } + }, + "5aaf8369f19346fb9ef6e83bee77706c": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_c2c6fcdbd2364ecf97382dc9c7c14eba", + "placeholder": "", + "style": "IPY_MODEL_b777873aaae545fea4cbc185254555fd", + "value": " 16/16 [00:02<00:00, 10.39it/s]" + } + }, + "5be330fcf8c148eeaa7ff2c86c669714": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "5d9a2f9e66014beebfee3d1b399c9c80": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "5dd2b94a9e9f4eafaeb0e369fc960d7f": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_a6344a7197a54414804dd8d4a19430d2", + "IPY_MODEL_93239cdb5ea046728cd5d952c5718ac1", + "IPY_MODEL_fc12e0be1fbc45ac9d8e3a50cd58ed39" + ], + "layout": "IPY_MODEL_ab48f5c1c115446888fe6768385047b2" + } + }, + "5efa58b1a4d7404b9dcfc7e3da97dfb5": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_c63a966f6a104fd6b563809350f76ef0", + "IPY_MODEL_7e1fee12c4274ddc9c8c9b107ec1bf03", + "IPY_MODEL_8a6e60a408194cefb30e0c567e54c5b2" + ], + "layout": "IPY_MODEL_c8de4b3a67a14901a41b7ab5fcfef1d8" + } + }, + "6172621fe6474774a569e7f543d701c0": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "63c7786ad23b49dd9328cf3101fca03b": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_df73481b726c44d9944c8fa63287a60c", + "placeholder": "", + "style": "IPY_MODEL_7d722aa2bfb34bcca0f8d3802bfddf11", + "value": "100%" + } + }, + "63ca01dc63d84bfd851c5a3c5bb39699": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "6752b91596a646ddbfef818ee63ab40b": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "6765c1f60581479fa94407eb2e3085fb": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_133677d36e674c1893339c00f4c39170", + "IPY_MODEL_a2834dd0211d430f84398e73740bd5bb", + "IPY_MODEL_307c00f3dfc2480fac3d5e4e5be98742" + ], + "layout": "IPY_MODEL_729f331381b849d3a2774a914f25dec6" + } + }, + "67d702f1e5c74b1589ef017a98442ab4": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_a2fe8be526b44a7bbe1da23e1ef95680", + "placeholder": "", + "style": "IPY_MODEL_a3ada5d5c7b849e9afa0f1e2181967c3", + "value": "100%" + } + }, + "69021f9d497f480c818b7b41c26d1c75": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "697fd62a7df44fbbbcd718a674e44c4a": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_b85e41d6779543df9857b56cf6677b0b", + "placeholder": "", + "style": "IPY_MODEL_41f57141ef1f4aa78987a53175572d5b", + "value": " 16/16 [00:04<00:00, 4.46it/s]" + } + }, + "69fe6cbcdace44dc883653a4c63491d6": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_67d702f1e5c74b1589ef017a98442ab4", + "IPY_MODEL_53d13e52cb114d6ea781d7d10c9415fe", + "IPY_MODEL_697fd62a7df44fbbbcd718a674e44c4a" + ], + "layout": "IPY_MODEL_7065b7f0ad194f6d90d5d7619ed60076" + } + }, + "6a07799a8784410884c71879e3cfd82c": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_400889d6caa448c880e1a21532409617", + "placeholder": "", + "style": "IPY_MODEL_2d050f7835184b93b8d4f30dbd7cc16a", + "value": " 403/403 [03:55<00:00, 1.73it/s]" + } + }, + "6a3c09a0bef8461eb4f42c12f3fbf252": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "6b92eabd9cc14a41a5b8c06a95f2a461": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "6cf087a2a16744a18200792194788ae2": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "6da1560e8fb749c29682bb95d838f7d4": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_5d9a2f9e66014beebfee3d1b399c9c80", + "placeholder": "", + "style": "IPY_MODEL_e8b93f3076ad4f4e830fee1bb86443f9", + "value": " 403/403 [03:55<00:00, 1.77it/s]" + } + }, + "7065b7f0ad194f6d90d5d7619ed60076": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "711c3945a9764bff98e986c7b139c60d": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "71874a3bc6734ce88ddff76ca042b409": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "729f331381b849d3a2774a914f25dec6": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "74c2704c43574db6a1a101953126f0f6": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "74ea41607b834f30a75179017fe09ab4": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "75c7666da77744a185cdb21b810c9007": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "774dffcb789e46c9bfa00da8f47de45d": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_3cd3e98ef2364ad6be4711c9621e3404", + "max": 16, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_9bb22293ff754067bbae1c0e006f630a", + "value": 16 + } + }, + "77845f14cb3948c381d60fac9e11ea2e": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "78e85cb47f5d460ba5e6b14c6631abfc": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "79a42c9cf3a940e7ab9ab6ed26a7ed93": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "7aeebaaf7f40434aa5cda9c8b560ecfa": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_0168b617288942379053f80fcf791606", + "placeholder": "", + "style": "IPY_MODEL_9d0ac0ec649f46abb5a635b524504c53", + "value": " 16/16 [00:02<00:00, 9.87it/s]" + } + }, + "7c69e3e5fe1f4cba82a797ad8509c69d": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "7cae68c449ad4b15ad5a95dff361745e": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_c3f5281c0071455fbf4ddf888bc8a000", + "max": 16, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_9d5e77107c4243d986c4ffd19f9b48af", + "value": 16 + } + }, + "7d2b868920f54a0c9f042c1f32018711": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_cabdd27082564769a84d309322faed41", + "IPY_MODEL_aa03a9e03f73454cb2390208c4908a42", + "IPY_MODEL_3eefe02dae684c1c9c008e54bee40417" + ], + "layout": "IPY_MODEL_93fc6e5c74b1499185237ea99264c66d" + } + }, + "7d722aa2bfb34bcca0f8d3802bfddf11": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "7e1fee12c4274ddc9c8c9b107ec1bf03": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_8fa4c37a95cc4c60a8254b6afc9ee3f7", + "max": 16, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_958a2e10af3247d5a68baffc0fdbaf84", + "value": 16 + } + }, + "7e2b65ad965549778444697f74e71f08": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_d84d1932c9f847cf87c8ae3d9c77bec9", + "placeholder": "", + "style": "IPY_MODEL_adb9fb37522343d9878d8f9d875c760b", + "value": " 403/403 [03:55<00:00, 1.78it/s]" + } + }, + "7f51aa6075e14485bbb532b374247855": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "8099c4ca7a384d949bccbe314e98521a": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_b8fc39b9aed84495bc689704ef8526e6", + "max": 403, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_f1825a71f6f64426b03e39c541f06136", + "value": 403 + } + }, + "81231484ce764d7d8f08b835a60b6039": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "82bc7f9ad69846248a6b6ea375274c7d": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "84a24649b3b245a9b8b76930939c0969": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "84d9e268dc7e43bba8fb8ac3bdc2a3fb": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "86ed55ca8f154b009d270be60533761e": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_d58d868b0b714964885554ce7446d8c4", + "max": 403, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_549d4f0df80f4040a5c183991e2fe9bb", + "value": 403 + } + }, + "87637a6cdedf4ea19cc4eb4cb459ba5c": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "87e5e33c4a2346f6a5f208c473ba870b": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "8992f1b1a84e41bbb3636aaaa8648d50": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "8a094b4c0441477f8758f5ec8ea30fd9": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_f52365477a9d4f35aed9bf321bc91ce8", + "IPY_MODEL_86ed55ca8f154b009d270be60533761e", + "IPY_MODEL_6a07799a8784410884c71879e3cfd82c" + ], + "layout": "IPY_MODEL_53ca8bea715049f983c80cd510f6fe84" + } + }, + "8a6e60a408194cefb30e0c567e54c5b2": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_ee96aae30c844fbbac12f746244f974b", + "placeholder": "", + "style": "IPY_MODEL_84a24649b3b245a9b8b76930939c0969", + "value": " 16/16 [00:04<00:00, 4.45it/s]" + } + }, + "8d7738dd895a4c1898b1071ff71d0160": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "8f1ab4f675be47d7a8949fbd44e559ee": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_8d7738dd895a4c1898b1071ff71d0160", + "placeholder": "", + "style": "IPY_MODEL_058c50a31d9b4520af109eedfc39c056", + "value": " 403/403 [03:54<00:00, 1.78it/s]" + } + }, + "8fa4c37a95cc4c60a8254b6afc9ee3f7": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "93239cdb5ea046728cd5d952c5718ac1": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_1b0adead9311477c8901da39a85f506d", + "max": 16, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_71874a3bc6734ce88ddff76ca042b409", + "value": 16 + } + }, + "93fc6e5c74b1499185237ea99264c66d": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "94a650bcbd80491081c1b500f9bdde31": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "958a2e10af3247d5a68baffc0fdbaf84": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "977ff720f0dd40809f6c79fe472b735e": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "988554face9d422b9b9d7ec15b9f8f35": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "9bb22293ff754067bbae1c0e006f630a": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "9cae0b373fea4e4e825bccf59bae9d8b": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "9d0ac0ec649f46abb5a635b524504c53": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "9d5e77107c4243d986c4ffd19f9b48af": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "9f4efda38b02479ab5148a7f1be85898": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_10c5f59cef0f43c88cda68a6e0a2448a", + "IPY_MODEL_1645b680a4c4437d833c4e159b717468", + "IPY_MODEL_c6893a93d0f04a86ade694b9e3c4b4c9" + ], + "layout": "IPY_MODEL_b4bd0a4cc8e049ca9a0071736e876ea4" + } + }, + "a0631ef33079471c97476667c8fe5824": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "a08bb4188c50462385e59e8b42d5414d": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_f214e772f12c4f3f8d05c906c6b57d3d", + "max": 16, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_7c69e3e5fe1f4cba82a797ad8509c69d", + "value": 16 + } + }, + "a2834dd0211d430f84398e73740bd5bb": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_cdce3ac597ea41f9a1b83d6372aba449", + "max": 16, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_b442ab7d23cd414ca0e375bdad0e923c", + "value": 16 + } + }, + "a2fe8be526b44a7bbe1da23e1ef95680": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "a3ada5d5c7b849e9afa0f1e2181967c3": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "a615992bd57c4267932b7d4b103e33e8": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "a6344a7197a54414804dd8d4a19430d2": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_334551a828d04b33a0ed73d335c5744a", + "placeholder": "", + "style": "IPY_MODEL_b9b61fe2bb92437ba81882aa4dad9c4a", + "value": "100%" + } + }, + "a72e0aec7ebc4f65a6e62f95f26b6e33": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "a8b6874e76c7479882606013289b42dc": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_87637a6cdedf4ea19cc4eb4cb459ba5c", + "placeholder": "", + "style": "IPY_MODEL_2927b8c2167f404d812b5fb6ca2cbe48", + "value": " 403/403 [03:55<00:00, 1.77it/s]" + } + }, + "aa03a9e03f73454cb2390208c4908a42": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_eba047c7a6b2457c8ea2046239f8e55c", + "max": 403, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_21aa8ec04be2464295c755603f8bc2a4", + "value": 403 + } + }, + "aa3099cb4a84476cabec49993e7e75ef": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_43098603cb834b11aacbe2123b394071", + "IPY_MODEL_7cae68c449ad4b15ad5a95dff361745e", + "IPY_MODEL_e41132385f42489ba1150213a4351adb" + ], + "layout": "IPY_MODEL_94a650bcbd80491081c1b500f9bdde31" + } + }, + "aa957a6c8e5e456990f1a2cd8a4e3762": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "ab446d1802304e10b0ac3e3b39abce14": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "ab48f5c1c115446888fe6768385047b2": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "ab733440d25949a7a02f84d7ef2e75a4": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "adb9fb37522343d9878d8f9d875c760b": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "aec2f6336d2b49aa8851e8c829b40a3f": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "af29998c14de43dcb4e5d337ea1987d5": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_4f03e14b0a1d4a70a77a79c218822c33", + "IPY_MODEL_19ae24edfd094eb3903f9a92c909a770", + "IPY_MODEL_2c04efb851ee48f3b91423236614f256" + ], + "layout": "IPY_MODEL_321150e17ce0479385fc1dbfae365da4" + } + }, + "b0a8901bd1b04dd7b20edf84f377295c": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_55b4c5b37192419295bf4717290ef9dc", + "IPY_MODEL_067c0b2648634d65971be53ac05c6ebd", + "IPY_MODEL_6da1560e8fb749c29682bb95d838f7d4" + ], + "layout": "IPY_MODEL_11dae279dee54c289db7148b1ff31636" + } + }, + "b362ab5da06f4f74b5af3c4711e4d121": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "b3d716b99ede49b08da78dac38628125": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "b442ab7d23cd414ca0e375bdad0e923c": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "b44b6c0760ab4694a15032e717f8bd22": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_30dad6e494e145d3bee510e356dc0da2", + "IPY_MODEL_bdb845bc132e4288af4e3bf6e4ce8f10", + "IPY_MODEL_0806e9cc00a841319c29b526786d1e0b" + ], + "layout": "IPY_MODEL_711c3945a9764bff98e986c7b139c60d" + } + }, + "b4bd0a4cc8e049ca9a0071736e876ea4": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "b777873aaae545fea4cbc185254555fd": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "b85e41d6779543df9857b56cf6677b0b": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "b8fc39b9aed84495bc689704ef8526e6": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "b9b61fe2bb92437ba81882aa4dad9c4a": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "ba4b8e385cb44a0489235aa4cf44a754": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "bd1053c775aa48a29f2862a7130b38ee": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_3a5392e7c90c4a1ebd8b089d4eb10e42", + "IPY_MODEL_774dffcb789e46c9bfa00da8f47de45d", + "IPY_MODEL_7aeebaaf7f40434aa5cda9c8b560ecfa" + ], + "layout": "IPY_MODEL_22f6797e64db4fdf9eff9f32bb6d2d52" + } + }, + "bdb845bc132e4288af4e3bf6e4ce8f10": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_fbd3bb63b7ac4b8cbcff584d49226930", + "max": 403, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_fc6829f4240840ddb10ba194562a3127", + "value": 403 + } + }, + "bdba44b042924f5087b576248b8070e7": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "c03fe86962434903a75be0ea95d2beeb": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "c2c6fcdbd2364ecf97382dc9c7c14eba": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "c3f5281c0071455fbf4ddf888bc8a000": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "c54ee69a395a4a338660a0b3c3eb519f": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_3e081ee3984e45b8863dfca477fdc057", + "max": 403, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_02bf462aafab42d5a282c6044f0924af", + "value": 403 + } + }, + "c569ca56532a48b0a51df650aabce06c": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_32a495107a5f4a8e8fe72e281f5ee47d", + "placeholder": "", + "style": "IPY_MODEL_41f59e7f9fbe4fa29d7850192dbf02ff", + "value": " 403/403 [02:14<00:00, 3.04it/s]" + } + }, + "c579b7c7d039483e8b8dcc033b3201d2": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "c63a966f6a104fd6b563809350f76ef0": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_988554face9d422b9b9d7ec15b9f8f35", + "placeholder": "", + "style": "IPY_MODEL_2b5905d64d094e249a200e554c944563", + "value": "100%" + } + }, + "c6893a93d0f04a86ade694b9e3c4b4c9": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_77845f14cb3948c381d60fac9e11ea2e", + "placeholder": "", + "style": "IPY_MODEL_17f07573df3f4697aa7d50e725fa9fe8", + "value": " 16/16 [00:04<00:00, 4.48it/s]" + } + }, + "c8de4b3a67a14901a41b7ab5fcfef1d8": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "c8e8273720454cc2957f61626cac2034": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "c9d6790d51d04b26ac40e730c118828d": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "cabdd27082564769a84d309322faed41": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_08e8ac31b1e74198b3b6ccdf956bebd7", + "placeholder": "", + "style": "IPY_MODEL_6a3c09a0bef8461eb4f42c12f3fbf252", + "value": "100%" + } + }, + "cba7023224ce4008a1a84d2e68c4b10b": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "cc3d0595159c49c8a54e3cda01bafb70": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_f61fc34a0ee94f9bbc0a6c9bcfa06a2b", + "max": 403, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_d115340a713445b59302c60387644de4", + "value": 403 + } + }, + "ccd0badc672f44c09ab50e18bfe58cee": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_446ce98237e74bceb7665c2e20ab3750", + "IPY_MODEL_8099c4ca7a384d949bccbe314e98521a", + "IPY_MODEL_7e2b65ad965549778444697f74e71f08" + ], + "layout": "IPY_MODEL_f450a00db3a54f9b8b49c1ad04177346" + } + }, + "cdce3ac597ea41f9a1b83d6372aba449": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "ce525d1dc5734622b73c4e0864388f75": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "cfbaf53d78fd4120b80821e9ebe1707b": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_b362ab5da06f4f74b5af3c4711e4d121", + "max": 403, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_8992f1b1a84e41bbb3636aaaa8648d50", + "value": 403 + } + }, + "d0551e7bf98c4d56a667e8579b7a8394": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_568155b1e8bd4b7f8fb99babbcb32acd", + "max": 16, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_ab733440d25949a7a02f84d7ef2e75a4", + "value": 16 + } + }, + "d115340a713445b59302c60387644de4": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "d46754dfbb3e496190260e65022194b3": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_9cae0b373fea4e4e825bccf59bae9d8b", + "placeholder": "", + "style": "IPY_MODEL_dcb55e706ca5439f99a3b199990b78a3", + "value": "100%" + } + }, + "d58d868b0b714964885554ce7446d8c4": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "d61bc0378f9d4052b288557593fec4a7": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "d84d1932c9f847cf87c8ae3d9c77bec9": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "dcb55e706ca5439f99a3b199990b78a3": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "df73481b726c44d9944c8fa63287a60c": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "e26a18a5c5ad4bbcaba21c74cedb43be": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "e34cb60c67a940b083d7d722cfe07b9e": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "e41132385f42489ba1150213a4351adb": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_c9d6790d51d04b26ac40e730c118828d", + "placeholder": "", + "style": "IPY_MODEL_1141c0e0d2c041bb9e05253b49117b21", + "value": " 16/16 [00:02<00:00, 10.18it/s]" + } + }, + "e6282327f809437083bfd0288e701fef": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "e776baac3c13419d974722e1a4b36261": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_3755259c35754581a5fc228e90445edc", + "placeholder": "", + "style": "IPY_MODEL_e26a18a5c5ad4bbcaba21c74cedb43be", + "value": "100%" + } + }, + "e8b93f3076ad4f4e830fee1bb86443f9": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "e9b3bda8a95a40a7822961b84a39334c": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "eba047c7a6b2457c8ea2046239f8e55c": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "ec630b4bb08b471f8c06057f9f030133": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "ed591a7ff2f0403188f9f25f4465d80e": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "ee96aae30c844fbbac12f746244f974b": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "f1309ee098df4c3897ed4cc7c4e54663": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "f1825a71f6f64426b03e39c541f06136": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "f214e772f12c4f3f8d05c906c6b57d3d": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "f3f20217269545d4abdbbfae3f3bf08e": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "f450a00db3a54f9b8b49c1ad04177346": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "f52365477a9d4f35aed9bf321bc91ce8": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_f6627cb15852455cae3d5ec169ff2062", + "placeholder": "", + "style": "IPY_MODEL_f3f20217269545d4abdbbfae3f3bf08e", + "value": "100%" + } + }, + "f5d76345d11a4c3883f4bc728f1f7b67": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_74ea41607b834f30a75179017fe09ab4", + "max": 403, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_82bc7f9ad69846248a6b6ea375274c7d", + "value": 403 + } + }, + "f61fc34a0ee94f9bbc0a6c9bcfa06a2b": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "f6627cb15852455cae3d5ec169ff2062": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "fa65378678c74db7985eeecdc4ec2e8a": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "fb7579ebc5124ee9b2de23f6dc2bba67": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "fbd3bb63b7ac4b8cbcff584d49226930": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "fc12e0be1fbc45ac9d8e3a50cd58ed39": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_e9b3bda8a95a40a7822961b84a39334c", + "placeholder": "", + "style": "IPY_MODEL_178cc7579885416e8587d67b3e020989", + "value": " 16/16 [00:02<00:00, 10.43it/s]" + } + }, + "fc625b9031b24690b10cc9408a678ae1": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_ce525d1dc5734622b73c4e0864388f75", + "placeholder": "", + "style": "IPY_MODEL_63ca01dc63d84bfd851c5a3c5bb39699", + "value": "100%" + } + }, + "fc6829f4240840ddb10ba194562a3127": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "fceeb818a6c24751aadf5b09c9dba435": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "fe703c6001554401a9e9f52836e6ba9d": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_63c7786ad23b49dd9328cf3101fca03b", + "IPY_MODEL_f5d76345d11a4c3883f4bc728f1f7b67", + "IPY_MODEL_22598c3d37684f848f0581fa105b5b23" + ], + "layout": "IPY_MODEL_7f51aa6075e14485bbb532b374247855" + } + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/integrations/torchvision/tutorials/docs-torchvision-sparsify-from-scratch-mobilenetv2-beans.ipynb b/integrations/torchvision/tutorials/docs-torchvision-sparsify-from-scratch-mobilenetv2-beans.ipynb new file mode 100644 index 00000000000..c01b31342a6 --- /dev/null +++ b/integrations/torchvision/tutorials/docs-torchvision-sparsify-from-scratch-mobilenetv2-beans.ipynb @@ -0,0 +1,2115 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "00e081b7", + "metadata": {}, + "source": [ + "# Sparsifying MobileNetv2 from Scratch (Beans)\n", + "\n", + "In this example, we will demonstrate how to sparsify an image classification model from scratch using SparseML's PyTorch integration. We train and prune [MobileNetv2](https://pytorch.org/vision/main/models/generated/torchvision.models.mobilenet_v2.html) on the downstream [Beans dataset](https://huggingface.co/datasets/beans) using the Global Magnitude Pruning algorithm. \n", + "\n", + "## Agenda\n", + "\n", + "There are a few steps:\n", + "\n", + " 1. Setup the dataset\n", + " 2. Setup the PyTorch training loop\n", + " 3. Train a dense version of MobileNetv2\n", + " 4. Run the GMP pruning algorithm on the dense model\n", + " \n", + "## Installation\n", + "\n", + "Install SparseML with `pip`:\n", + "\n", + "```\n", + "pip install sparseml[torchvision]\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "1ad80edf", + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "import sparseml\n", + "import torchvision\n", + "from sparseml.pytorch.optim import ScheduledModifierManager\n", + "from sparseml.pytorch.utils import TensorBoardLogger, ModuleExporter, get_prunable_layers, tensor_sparsity\n", + "from torch.utils.data import DataLoader\n", + "from torch.nn import CrossEntropyLoss\n", + "from torch.optim import Adam\n", + "from torchvision import transforms\n", + "from tqdm.auto import tqdm\n", + "import math\n", + "import datasets" + ] + }, + { + "cell_type": "markdown", + "id": "0d30f71c", + "metadata": {}, + "source": [ + "## Step 1: Setup Dataset\n", + "\n", + "Beans leaf dataset is a set of images of diseased and healthy leaves. Based on a leaf image, the goal of this task is to predict the disease type (Angular Leaf Spot and Bean Rust), if any.\n", + "\n", + "We will use the Hugging Face `datasets` library to download the data and the torchvision `ImageFolder` in the training loop.\n", + "\n", + "[Checkout the dataset card](https://huggingface.co/datasets/beans)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "f8eb3642", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Found cached dataset beans (/home/ubuntu/.cache/huggingface/datasets/beans/default/0.0.0/90c755fb6db1c0ccdad02e897a37969dbf070bed3755d4391e269ff70642d791)\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7a630bb60c4a4413a0d43039cd9ac5d9", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "beans_dataset = datasets.load_dataset(\"beans\")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "b06fc4fd", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/home/ubuntu/.cache/huggingface/datasets/downloads/extracted/7ad2d437b751e134577576a32849c44a9ade89297680ad5f6a64051e2108810b/train/angular_leaf_spot/angular_leaf_spot_train.0.jpg\n", + "/home/ubuntu/.cache/huggingface/datasets/downloads/extracted/1141f86479bc0bb56c75616d153591cc8299d1ea4edc53bb1ab65edd2c65b240/validation/angular_leaf_spot/angular_leaf_spot_val.0.jpg\n" + ] + } + ], + "source": [ + "print(beans_dataset[\"train\"][0][\"image_file_path\"])\n", + "print(beans_dataset[\"validation\"][0][\"image_file_path\"])" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "4ecdebad", + "metadata": {}, + "outputs": [], + "source": [ + "train_path = \"/home/ubuntu/.cache/huggingface/datasets/downloads/extracted/eeb026374cf5ecfd5f40131a3159be9b9055ac21a3da11690e7eb4d117c99eee/train\"\n", + "val_path = \"/home/ubuntu/.cache/huggingface/datasets/downloads/extracted/f287261265d2f9a3e8f87a5526a54d1847b17f7c3ec5714e5719432f2b3e4a73/validation\" " + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "7d180bbc", + "metadata": {}, + "outputs": [], + "source": [ + "NUM_LABELS = 3\n", + "BATCH_SIZE = 32\n", + "\n", + "# imagenet transforms\n", + "imagenet_transform = transforms.Compose([\n", + " transforms.Resize(size=256, interpolation=transforms.InterpolationMode.BILINEAR, max_size=None, antialias=None),\n", + " transforms.CenterCrop(size=(224, 224)),\n", + " transforms.ToTensor(),\n", + " transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n", + "])\n", + "\n", + "# datasets\n", + "train_dataset = torchvision.datasets.ImageFolder(\n", + " root=train_path,\n", + " transform=imagenet_transform\n", + ")\n", + "\n", + "val_dataset = torchvision.datasets.ImageFolder(\n", + " root=val_path,\n", + " transform=imagenet_transform\n", + ")\n", + "\n", + "# dataloaders\n", + "train_loader = DataLoader(train_dataset, BATCH_SIZE, shuffle=True, pin_memory=True, num_workers=16)\n", + "val_loader = DataLoader(val_dataset, BATCH_SIZE, shuffle=False, pin_memory=True, num_workers=16)" + ] + }, + { + "cell_type": "markdown", + "id": "132fc514", + "metadata": {}, + "source": [ + "## Step 2: Setup PyTorch Training Loop\n", + "\n", + "We will use this training loop below. This is standard PyTorch functionality." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "c968c098", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cuda\n" + ] + } + ], + "source": [ + "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n", + "print(device)\n", + "\n", + "def run_model_one_epoch(model, data_loader, criterion, device, train=False, optimizer=None):\n", + " if train:\n", + " model.train()\n", + " else:\n", + " model.eval()\n", + "\n", + " running_loss = 0.0\n", + " total_correct = 0\n", + " total_predictions = 0\n", + "\n", + " # loop through batches\n", + " for step, (inputs, labels) in tqdm(enumerate(data_loader), total=len(data_loader)):\n", + " inputs = inputs.to(device)\n", + " labels = labels.to(device)\n", + "\n", + " if train:\n", + " optimizer.zero_grad()\n", + "\n", + " # compute loss, run backpropogation\n", + " outputs = model(inputs) # model returns logits\n", + " loss = criterion(outputs, labels)\n", + " if train:\n", + " loss.backward()\n", + " optimizer.step()\n", + "\n", + " running_loss += loss.item()\n", + "\n", + " # run evaluation\n", + " predictions = outputs.argmax(dim=1)\n", + " total_correct += torch.sum(predictions == labels).item()\n", + " total_predictions += inputs.size(0)\n", + "\n", + " # return loss and evaluation metric\n", + " loss = running_loss / (step + 1.0)\n", + " accuracy = total_correct / total_predictions\n", + " return loss, accuracy" + ] + }, + { + "cell_type": "markdown", + "id": "a3521e78", + "metadata": {}, + "source": [ + "## **Step 3: Train MobileNet-v2 on Beans**\n", + "\n", + "First, we will train a dense version of MobileNetv2 on the Beans dataset." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "4d554578", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# download pre-trained model, setup classification head\n", + "model = torchvision.models.mobilenet_v2(weights=torchvision.models.MobileNet_V2_Weights.DEFAULT)\n", + "model.classifier[1] = torch.nn.Linear(model.classifier[1].in_features, NUM_LABELS)\n", + "model.to(device)\n", + "\n", + "# setup loss function and optimizer\n", + "criterion = CrossEntropyLoss()\n", + "optimizer = Adam(model.parameters(), lr=8e-3) # lr will be override by sparseml" + ] + }, + { + "cell_type": "markdown", + "id": "31064d5c", + "metadata": {}, + "source": [ + "Next, we will use SparseML's recipes to set the hyperparameters of training loop. In this case, we will use the following recipe:\n", + "\n", + "```yaml\n", + "# Epoch and Learning-Rate variables\n", + "num_epochs: 10.0\n", + "init_lr: 0.0005\n", + "\n", + "training_modifiers:\n", + " - !EpochRangeModifier\n", + " start_epoch: 0.0\n", + " end_epoch: eval(num_epochs)\n", + "\n", + " - !LearningRateFunctionModifier\n", + " final_lr: 0.0\n", + " init_lr: eval(init_lr)\n", + " lr_func: cosine\n", + " start_epoch: 0.0\n", + " end_epoch: eval(num_epochs)\n", + "```\n", + "\n", + "As you can see, the recipe includes an `!EpochRangeModifier` and a `!LearningRateFunctionModifier`. These modifiers simply set the number of epochs to train for and the learning rate schedule. As a result, the final model will be dense." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "2723a40f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\r\n", + "# Epoch and Learning-Rate variables\r\n", + "num_epochs: 10.0\r\n", + "init_lr: 0.0005\r\n", + "\r\n", + "training_modifiers:\r\n", + " - !EpochRangeModifier\r\n", + " start_epoch: 0.0\r\n", + " end_epoch: eval(num_epochs)\r\n", + "\r\n", + " - !LearningRateFunctionModifier\r\n", + " final_lr: 0.0\r\n", + " init_lr: eval(init_lr)\r\n", + " lr_func: cosine\r\n", + " start_epoch: 0.0\r\n", + " end_epoch: eval(num_epochs)" + ] + } + ], + "source": [ + "!cat ./recipes/mobilenetv2-beans-dense-recipe.yaml" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "cec41d57", + "metadata": {}, + "outputs": [], + "source": [ + "dense_recipe_path = \"./recipes/mobilenetv2-beans-dense-recipe.yaml\"" + ] + }, + { + "cell_type": "markdown", + "id": "f7cba342", + "metadata": {}, + "source": [ + "Next, we use SparseML's `ScheduledModifierManager` to parse and apply the recipe. The `manager.modify` function modifies and wraps the `model` and `optimizer` with the instructions from the recipe. You can use the `model` and `optimizer` just like standard PyTorch objects." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "1749e00d", + "metadata": {}, + "outputs": [], + "source": [ + "# create ScheduledModifierManager and Optimizer wrapper\n", + "manager = ScheduledModifierManager.from_yaml(dense_recipe_path)\n", + "optimizer = manager.modify(model, optimizer, steps_per_epoch=len(train_loader))" + ] + }, + { + "cell_type": "markdown", + "id": "a00c4ceb", + "metadata": {}, + "source": [ + "Kick off the transfer learning loop. Our run reached ~99% validation accuracy after 10 epochs." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "d00d175b", + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running Training Epoch 1/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "5cc895557d43463fa06855d8cb6a04b6", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 1/10\n", + "Training Loss: 0.5145365252639308\n", + "Top 1 Acc: 0.8268858800773694\n", + "\n", + "Running Validation Epoch 1/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d7e8b1b81291424d88d0bde70b3b21ee", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 1/10\n", + "Val Loss: 0.13084974102675914\n", + "Top 1 Acc: 0.9398496240601504\n", + "\n", + "Running Training Epoch 2/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c1fe04fab0584f509ceb2cba7a20e70f", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 2/10\n", + "Training Loss: 0.1433423740619963\n", + "Top 1 Acc: 0.9497098646034816\n", + "\n", + "Running Validation Epoch 2/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "daf68b9458b84bb49a33f78bf0c5a68d", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 2/10\n", + "Val Loss: 0.06366700865328312\n", + "Top 1 Acc: 0.9774436090225563\n", + "\n", + "Running Training Epoch 3/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "3151d6a608db42a792372a3aa4467e38", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 3/10\n", + "Training Loss: 0.04070456024033554\n", + "Top 1 Acc: 0.9922630560928434\n", + "\n", + "Running Validation Epoch 3/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "2ee08ae3a7144f75831f9e1cd3d7b454", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 3/10\n", + "Val Loss: 0.06802571751177311\n", + "Top 1 Acc: 0.9774436090225563\n", + "\n", + "Running Training Epoch 4/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "dc12cd7f00284ea58433ed0a5c826791", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 4/10\n", + "Training Loss: 0.03408790949844953\n", + "Top 1 Acc: 0.9903288201160542\n", + "\n", + "Running Validation Epoch 4/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "facab31d1719407d95198e46bd9444b6", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 4/10\n", + "Val Loss: 0.0302915308624506\n", + "Top 1 Acc: 0.9924812030075187\n", + "\n", + "Running Training Epoch 5/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "59c280ab06744fbeb0234b55667c9fd4", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 5/10\n", + "Training Loss: 0.014188278910957954\n", + "Top 1 Acc: 0.9980657640232108\n", + "\n", + "Running Validation Epoch 5/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "79553b09130d408f90e9825fcb16c1e5", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 5/10\n", + "Val Loss: 0.036852234788239\n", + "Top 1 Acc: 0.9774436090225563\n", + "\n", + "Running Training Epoch 6/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "00eeaceb759d4bedade5095b8bccfc14", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 6/10\n", + "Training Loss: 0.008212485654053815\n", + "Top 1 Acc: 0.9990328820116054\n", + "\n", + "Running Validation Epoch 6/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "17012e571c1742d394678adda75e0a27", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 6/10\n", + "Val Loss: 0.023899264284409583\n", + "Top 1 Acc: 0.9924812030075187\n", + "\n", + "Running Training Epoch 7/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "8423061cd4b3428d81985783be66ae24", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 7/10\n", + "Training Loss: 0.003027547925188573\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Validation Epoch 7/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f2eeb131d20f474585d960b1756fc6a8", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 7/10\n", + "Val Loss: 0.02565102996304631\n", + "Top 1 Acc: 0.9924812030075187\n", + "\n", + "Running Training Epoch 8/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "94b20d80ad3b4c1d8536928b380a6306", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 8/10\n", + "Training Loss: 0.003363958947981397\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Validation Epoch 8/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "28472058de974ef48a845de629c800f9", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 8/10\n", + "Val Loss: 0.0232504392741248\n", + "Top 1 Acc: 0.9849624060150376\n", + "\n", + "Running Training Epoch 9/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "a7481a29e458478f9fd4113a025003dc", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 9/10\n", + "Training Loss: 0.004655612831949397\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Validation Epoch 9/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ff7d10297b3d4658a227df552c3a622d", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 9/10\n", + "Val Loss: 0.027894998691044746\n", + "Top 1 Acc: 0.9849624060150376\n", + "\n", + "Running Training Epoch 10/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ad177de3d1384cb4a32a97a3fd5f5c46", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 10/10\n", + "Training Loss: 0.01938260115937076\n", + "Top 1 Acc: 0.9990328820116054\n", + "\n", + "Running Validation Epoch 10/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "8637fb0cea6e45a5b47dcea94cf7cc71", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 10/10\n", + "Val Loss: 0.027051440824288876\n", + "Top 1 Acc: 0.9849624060150376\n", + "\n" + ] + } + ], + "source": [ + "# run transfer learning\n", + "epoch = 0\n", + "for epoch in range(manager.max_epochs):\n", + " # run training loop\n", + " epoch_name = f\"{epoch + 1}/{manager.max_epochs}\"\n", + " print(f\"Running Training Epoch {epoch_name}\")\n", + " train_loss, train_acc = run_model_one_epoch(model, train_loader, criterion, device, train=True, optimizer=optimizer)\n", + " print(f\"Training Epoch: {epoch_name}\\nTraining Loss: {train_loss}\\nTop 1 Acc: {train_acc}\\n\")\n", + "\n", + " # run validation loop\n", + " print(f\"Running Validation Epoch {epoch_name}\")\n", + " val_loss, val_acc = run_model_one_epoch(model, val_loader, criterion, device)\n", + " print(f\"Validation Epoch: {epoch_name}\\nVal Loss: {val_loss}\\nTop 1 Acc: {val_acc}\\n\")\n", + "\n", + "manager.finalize(model)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "11fa4cf2", + "metadata": {}, + "outputs": [], + "source": [ + "from sparseml.pytorch.utils import ModuleExporter\n", + "\n", + "save_dir = \"dense_model\"\n", + "exporter = ModuleExporter(model, output_dir=save_dir)\n", + "exporter.export_pytorch(name=\"mobilenet-v2-dense-beans.pth\")" + ] + }, + { + "cell_type": "markdown", + "id": "273ce478", + "metadata": {}, + "source": [ + "## Step 4: Prune The Model\n", + "\n", + "With a model trained on Beans, we are now ready to apply the GMP algorithm to prune the model. The GMP algorithm is an interative pruning algorithm. At the end of each epoch, we identify the lowest magnitude weights (those closest to 0) and remove them from the network starting from an initial level of sparsity until a final level of sparsity. The remaining nonzero weights are then fine-tuned onto training dataset." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "8447d074", + "metadata": {}, + "outputs": [], + "source": [ + "checkpoint = torch.load(\"./dense_model/training/mobilenet-v2-dense-beans.pth\")\n", + "model = torchvision.models.mobilenet_v2()\n", + "model.classifier[1] = torch.nn.Linear(model.classifier[1].in_features, NUM_LABELS)\n", + "model.load_state_dict(checkpoint['state_dict'])\n", + "model.to(device)\n", + "\n", + "# setup loss function and optimizer, LR will be overriden by sparseml\n", + "criterion = CrossEntropyLoss()\n", + "optimizer = Adam(model.parameters(), lr=8e-3)" + ] + }, + { + "cell_type": "markdown", + "id": "1b188d60", + "metadata": {}, + "source": [ + "Next, we need to create a SparseML recipe which includes the GMP algorithm. The `!GlobalMagnitudePruningModifier` modifier instructs SparseML to apply the GMP algorithm at a global level (pruning the lowest magnitude weights across all layers).\n", + "\n", + "Firstly, we need to decide identify which parameters of the model to apply the GMP algorithm to. We can use the `get_prunable_layers` function to inspect:" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "44578399", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "features.0.0\n", + "features.1.conv.0.0\n", + "features.1.conv.1\n", + "features.2.conv.0.0\n", + "features.2.conv.1.0\n", + "features.2.conv.2\n", + "features.3.conv.0.0\n", + "features.3.conv.1.0\n", + "features.3.conv.2\n", + "features.4.conv.0.0\n", + "features.4.conv.1.0\n", + "features.4.conv.2\n", + "features.5.conv.0.0\n", + "features.5.conv.1.0\n", + "features.5.conv.2\n", + "features.6.conv.0.0\n", + "features.6.conv.1.0\n", + "features.6.conv.2\n", + "features.7.conv.0.0\n", + "features.7.conv.1.0\n", + "features.7.conv.2\n", + "features.8.conv.0.0\n", + "features.8.conv.1.0\n", + "features.8.conv.2\n", + "features.9.conv.0.0\n", + "features.9.conv.1.0\n", + "features.9.conv.2\n", + "features.10.conv.0.0\n", + "features.10.conv.1.0\n", + "features.10.conv.2\n", + "features.11.conv.0.0\n", + "features.11.conv.1.0\n", + "features.11.conv.2\n", + "features.12.conv.0.0\n", + "features.12.conv.1.0\n", + "features.12.conv.2\n", + "features.13.conv.0.0\n", + "features.13.conv.1.0\n", + "features.13.conv.2\n", + "features.14.conv.0.0\n", + "features.14.conv.1.0\n", + "features.14.conv.2\n", + "features.15.conv.0.0\n", + "features.15.conv.1.0\n", + "features.15.conv.2\n", + "features.16.conv.0.0\n", + "features.16.conv.1.0\n", + "features.16.conv.2\n", + "features.17.conv.0.0\n", + "features.17.conv.1.0\n", + "features.17.conv.2\n", + "features.18.0\n", + "classifier.1\n" + ] + } + ], + "source": [ + "# print parameters\n", + "for (name, layer) in get_prunable_layers(model):\n", + " print(f\"{name}\")" + ] + }, + { + "cell_type": "markdown", + "id": "7249f54d", + "metadata": {}, + "source": [ + "We will apply pruning to each of the convs and exclude the classifier layer (which is the final projection head). Fortunately, SparseML allows us to pass regexes to identify layers in the network, so we can use the following list to identify the relevant layers for pruning:\n", + " \n", + " - 'features.0.0.weight'\n", + " - 'features.18.0.weight'\n", + " - 're:features.*.conv.*.weight'\n", + " - 're:features.*.conv.*.*.weight'\n", + "\n", + "Here is what the recipe looks like:\n", + "\n", + "```yaml\n", + "# Epoch hyperparams\n", + "stabilization_epochs: 1.0\n", + "pruning_epochs: 9.0\n", + "finetuning_epochs: 5.0\n", + "\n", + "# Learning rate hyperparams\n", + "init_lr: 0.0005\n", + "final_lr: 0.00025\n", + "\n", + "# Pruning hyperparams\n", + "init_sparsity: 0.05\n", + "final_sparsity: 0.9\n", + "\n", + "# Stabalization Stage\n", + "training_modifiers:\n", + " - !EpochRangeModifier\n", + " start_epoch: 0.0\n", + " end_epoch: eval(stabilization_epochs + pruning_epochs + finetuning_epochs)\n", + " \n", + " - !SetLearningRateModifier\n", + " start_epoch: 0.0\n", + " learning_rate: eval(init_lr)\n", + "\n", + "# Pruning Stage\n", + "pruning_modifiers:\n", + " - !LearningRateFunctionModifier\n", + " init_lr: eval(init_lr)\n", + " final_lr: eval(final_lr)\n", + " lr_func: cosine\n", + " start_epoch: eval(stabilization_epochs)\n", + " end_epoch: eval(stabilization_epochs + pruning_epochs)\n", + " \n", + " - !GlobalMagnitudePruningModifier\n", + " init_sparsity: eval(init_sparsity)\n", + " final_sparsity: eval(final_sparsity)\n", + " start_epoch: eval(stabilization_epochs)\n", + " end_epoch: eval(stabilization_epochs + pruning_epochs)\n", + " update_frequency: 0.5\n", + " params: \n", + " - 'features.0.0.weight'\n", + " - 'features.18.0.weight'\n", + " - 're:features.*.conv.*.weight'\n", + " - 're:features.*.conv.*.*.weight'\n", + " leave_enabled: True\n", + "\n", + "# Finetuning Stage\n", + "finetuning_modifiers:\n", + " - !LearningRateFunctionModifier\n", + " init_lr: eval(init_lr)\n", + " final_lr: eval(final_lr)\n", + " lr_func: cosine\n", + " start_epoch: eval(stabilization_epochs + pruning_epochs)\n", + " end_epoch: eval(stabilization_epochs + pruning_epochs + finetuning_epochs)\n", + "```\n", + "\n", + "This recipe specifies that we will run the GMP algorithm for 9 epochs after 1 warmup epoch. We start at an init_sparsity level of 5% and gradually increase sparsity to a final_sparsity level of 90% following a cubic curve. The pruning is applied in an unstructured manner, meaning that any weight can be pruned.\n", + "\n", + "Over the final 5 epochs, we will fine-tune the 90% pruned model further. Since we set leave_enabled=True the sparsity level will be maintained as the fine-tuning occurs." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "ca5c28b2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# Epoch hyperparams\r\n", + "stabilization_epochs: 1.0\r\n", + "pruning_epochs: 9.0\r\n", + "finetuning_epochs: 5.0\r\n", + "\r\n", + "# Learning rate hyperparams\r\n", + "init_lr: 0.0005\r\n", + "final_lr: 0.00025\r\n", + "\r\n", + "# Pruning hyperparams\r\n", + "init_sparsity: 0.05\r\n", + "final_sparsity: 0.9\r\n", + "\r\n", + "# Stabalization Stage\r\n", + "training_modifiers:\r\n", + " - !EpochRangeModifier\r\n", + " start_epoch: 0.0\r\n", + " end_epoch: eval(stabilization_epochs + pruning_epochs + finetuning_epochs)\r\n", + " \r\n", + " - !SetLearningRateModifier\r\n", + " start_epoch: 0.0\r\n", + " learning_rate: eval(init_lr)\r\n", + "\r\n", + "# Pruning Stage\r\n", + "pruning_modifiers:\r\n", + " - !LearningRateFunctionModifier\r\n", + " init_lr: eval(init_lr)\r\n", + " final_lr: eval(final_lr)\r\n", + " lr_func: cosine\r\n", + " start_epoch: eval(stabilization_epochs)\r\n", + " end_epoch: eval(stabilization_epochs + pruning_epochs)\r\n", + " \r\n", + " - !GlobalMagnitudePruningModifier\r\n", + " init_sparsity: eval(init_sparsity)\r\n", + " final_sparsity: eval(final_sparsity)\r\n", + " start_epoch: eval(stabilization_epochs)\r\n", + " end_epoch: eval(stabilization_epochs + pruning_epochs)\r\n", + " update_frequency: 0.5\r\n", + " params: \r\n", + " - 'features.0.0.weight'\r\n", + " - 'features.18.0.weight'\r\n", + " - 're:features.*.conv.*.weight'\r\n", + " - 're:features.*.conv.*.*.weight'\r\n", + " leave_enabled: True\r\n", + "\r\n", + "# Finetuning Stage\r\n", + "finetuning_modifiers:\r\n", + " - !LearningRateFunctionModifier\r\n", + " init_lr: eval(init_lr)\r\n", + " final_lr: eval(final_lr)\r\n", + " lr_func: cosine\r\n", + " start_epoch: eval(stabilization_epochs + pruning_epochs)\r\n", + " end_epoch: eval(stabilization_epochs + pruning_epochs + finetuning_epochs)" + ] + } + ], + "source": [ + "!cat ./recipes/mobilenetv2-beans-pruning-recipe.yaml" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "b55a7c74", + "metadata": {}, + "outputs": [], + "source": [ + "pruning_recipe_path = \"./recipes/mobilenetv2-beans-pruning-recipe.yaml\"" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "68646bc7", + "metadata": {}, + "outputs": [], + "source": [ + "# create ScheduledModifierManager and Optimizer wrapper\n", + "manager = ScheduledModifierManager.from_yaml(pruning_recipe_path)\n", + "logger = TensorBoardLogger(log_path=\"./tensorboard_outputs\")\n", + "optimizer = manager.modify(model, optimizer, loggers=[logger], steps_per_epoch=len(train_loader))" + ] + }, + { + "cell_type": "markdown", + "id": "37d4b6a4", + "metadata": {}, + "source": [ + "Next, kick off the GMP training loop. \n", + "\n", + "As you can see, we use the wrapped `optimizer` and `model` in the same way as above. SparseML parsed the recipe and updated the `optimizer` with the logic of GMP algorithm from the recipe. This allows you to just the `optimizer` and `model` as usual, with all of the pruning-related logic specified by the declarative recipe interface.\n", + "\n", + "Our 90% pruned model reaches ~99% validation accuracy (vs ~98% for the dense model)." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "601c8c21", + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running Training Epoch 1/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "3b037b49d42c41abadc2bbab546e5760", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 1/15\n", + "Training Loss: 0.04981424145058334\n", + "Top 1 Acc: 0.988394584139265\n", + "\n", + "Running Validation Epoch 1/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "aa75f114f7754ea4a4b7509826d769e3", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 1/15\n", + "Val Loss: 0.06650052629411221\n", + "Top 1 Acc: 0.9774436090225563\n", + "\n", + "Running Training Epoch 2/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "50b86debcf3148a687d17c36c601c99d", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 2/15\n", + "Training Loss: 0.08335415836226082\n", + "Top 1 Acc: 0.9777562862669246\n", + "\n", + "Running Validation Epoch 2/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "e741553cb741416b98bfa577d529d575", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 2/15\n", + "Val Loss: 0.06197752933949232\n", + "Top 1 Acc: 0.9774436090225563\n", + "\n", + "Running Training Epoch 3/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "0b86b60f094e4d1e9338aaa664cdf901", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 3/15\n", + "Training Loss: 0.040097551427386476\n", + "Top 1 Acc: 0.9854932301740812\n", + "\n", + "Running Validation Epoch 3/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c2899c110f954430a41ed5a8410f21a4", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 3/15\n", + "Val Loss: 0.05052837722469121\n", + "Top 1 Acc: 0.9849624060150376\n", + "\n", + "Running Training Epoch 4/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "6c7cc173588c4ade9a5315a16ac9eec8", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 4/15\n", + "Training Loss: 0.03676384532203277\n", + "Top 1 Acc: 0.9893617021276596\n", + "\n", + "Running Validation Epoch 4/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "99aefcf3d0b2421a896fa2b9d03e4fc1", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 4/15\n", + "Val Loss: 0.08736732564866542\n", + "Top 1 Acc: 0.9624060150375939\n", + "\n", + "Running Training Epoch 5/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "37d08c11516b44fbaf3cdb52b46b5144", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 5/15\n", + "Training Loss: 0.03125915414244501\n", + "Top 1 Acc: 0.9932301740812379\n", + "\n", + "Running Validation Epoch 5/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "e2ff32388c1746588cc01452aa64e7bd", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 5/15\n", + "Val Loss: 0.09458159506320954\n", + "Top 1 Acc: 0.9924812030075187\n", + "\n", + "Running Training Epoch 6/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "8ff4dcbc05de41d5b22850148996c74c", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 6/15\n", + "Training Loss: 0.0748459067421429\n", + "Top 1 Acc: 0.9796905222437138\n", + "\n", + "Running Validation Epoch 6/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "5d12d2c66f06462aa9cc276d9ee2ea38", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 6/15\n", + "Val Loss: 0.20114150643348694\n", + "Top 1 Acc: 0.9699248120300752\n", + "\n", + "Running Training Epoch 7/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4fab3bd349f44218a93177ca9d73481f", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 7/15\n", + "Training Loss: 0.10897209077621951\n", + "Top 1 Acc: 0.965183752417795\n", + "\n", + "Running Validation Epoch 7/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4d54279b4f8d456eb485c6a749248603", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 7/15\n", + "Val Loss: 0.3452451154589653\n", + "Top 1 Acc: 0.8421052631578947\n", + "\n", + "Running Training Epoch 8/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "39115311d08a4bc6a94d8e266991cce7", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 8/15\n", + "Training Loss: 0.13403249407807985\n", + "Top 1 Acc: 0.9506769825918762\n", + "\n", + "Running Validation Epoch 8/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "a0cb864970ad4f4d928f59f34eaadeb4", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 8/15\n", + "Val Loss: 0.20368995219469072\n", + "Top 1 Acc: 0.9323308270676691\n", + "\n", + "Running Training Epoch 9/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "655cc448f70746e7bc20bd6e834ae19f", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 9/15\n", + "Training Loss: 0.12121003064693826\n", + "Top 1 Acc: 0.9671179883945842\n", + "\n", + "Running Validation Epoch 9/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "2d55e9450fae497e96b86211ca33812e", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 9/15\n", + "Val Loss: 0.11063596755266189\n", + "Top 1 Acc: 0.9774436090225563\n", + "\n", + "Running Training Epoch 10/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "2744a665b1094c96a80cbe44a87207cb", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 10/15\n", + "Training Loss: 0.09124855725376894\n", + "Top 1 Acc: 0.9642166344294004\n", + "\n", + "Running Validation Epoch 10/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "6779935332bb4ebdb701baedf3866911", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 10/15\n", + "Val Loss: 0.0751135416328907\n", + "Top 1 Acc: 0.9699248120300752\n", + "\n", + "Running Training Epoch 11/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4b84d196120844b9ba1254eda5a61c06", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 11/15\n", + "Training Loss: 0.04337389501884128\n", + "Top 1 Acc: 0.9912959381044487\n", + "\n", + "Running Validation Epoch 11/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "88d8406bbfcc4886a9415ace34de12a1", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 11/15\n", + "Val Loss: 0.034493994899094105\n", + "Top 1 Acc: 0.9774436090225563\n", + "\n", + "Running Training Epoch 12/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "afec4141ee4d4e4080fb460168a09534", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 12/15\n", + "Training Loss: 0.018291185736994852\n", + "Top 1 Acc: 0.9980657640232108\n", + "\n", + "Running Validation Epoch 12/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f21726e565b14415975169049d1c5931", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 12/15\n", + "Val Loss: 0.04321025339886546\n", + "Top 1 Acc: 0.9774436090225563\n", + "\n", + "Running Training Epoch 13/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "0eb6ef213d5f41758f2c89f31fb6aa01", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 13/15\n", + "Training Loss: 0.0146882157899778\n", + "Top 1 Acc: 0.9970986460348162\n", + "\n", + "Running Validation Epoch 13/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "9aeef2ccf0dd4fb8941bafd967316189", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 13/15\n", + "Val Loss: 0.03916811663657427\n", + "Top 1 Acc: 0.9924812030075187\n", + "\n", + "Running Training Epoch 14/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "32f885475f8049b2ab560ffbc4c9390f", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 14/15\n", + "Training Loss: 0.014786866712242816\n", + "Top 1 Acc: 0.9990328820116054\n", + "\n", + "Running Validation Epoch 14/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "2a55281ea41c4263874838cd59440ef9", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 14/15\n", + "Val Loss: 0.040105257043614985\n", + "Top 1 Acc: 0.9849624060150376\n", + "\n", + "Running Training Epoch 15/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b7bf416c8c5f4ee5893e170b01e1adcc", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/33 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 15/15\n", + "Training Loss: 0.007484704270168688\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Validation Epoch 15/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "2e9f4636ad844a869db5541b37f9732a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/5 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 15/15\n", + "Val Loss: 0.02973868220578879\n", + "Top 1 Acc: 0.9774436090225563\n", + "\n" + ] + } + ], + "source": [ + "# run GMP algorithm\n", + "epoch = 0\n", + "for epoch in range(manager.max_epochs):\n", + " # run training loop\n", + " epoch_name = f\"{epoch + 1}/{manager.max_epochs}\"\n", + " print(f\"Running Training Epoch {epoch_name}\")\n", + " train_loss, train_acc = run_model_one_epoch(model, train_loader, criterion, device, train=True, optimizer=optimizer)\n", + " print(f\"Training Epoch: {epoch_name}\\nTraining Loss: {train_loss}\\nTop 1 Acc: {train_acc}\\n\")\n", + "\n", + " # run validation loop\n", + " print(f\"Running Validation Epoch {epoch_name}\")\n", + " val_loss, val_acc = run_model_one_epoch(model, val_loader, criterion, device)\n", + " print(f\"Validation Epoch: {epoch_name}\\nVal Loss: {val_loss}\\nTop 1 Acc: {val_acc}\\n\")\n", + " \n", + " logger.log_scalar(\"Metrics/Loss (Train)\", train_loss, epoch)\n", + " logger.log_scalar(\"Metrics/Accuracy (Train)\", train_acc, epoch)\n", + " logger.log_scalar(\"Metrics/Loss (Validation)\", val_loss, epoch)\n", + " logger.log_scalar(\"Metrics/Accuracy (Validation)\", val_acc, epoch)\n", + " \n", + "manager.finalize(model)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "2bf48ed2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "features.0.0.weight: 0.4896\n", + "features.1.conv.0.0.weight: 0.4722\n", + "features.1.conv.1.weight: 0.5234\n", + "features.2.conv.0.0.weight: 0.5501\n", + "features.2.conv.1.0.weight: 0.2859\n", + "features.2.conv.2.weight: 0.4813\n", + "features.3.conv.0.0.weight: 0.6137\n", + "features.3.conv.1.0.weight: 0.4977\n", + "features.3.conv.2.weight: 0.6131\n", + "features.4.conv.0.0.weight: 0.5214\n", + "features.4.conv.1.0.weight: 0.2785\n", + "features.4.conv.2.weight: 0.5184\n", + "features.5.conv.0.0.weight: 0.6903\n", + "features.5.conv.1.0.weight: 0.5804\n", + "features.5.conv.2.weight: 0.7134\n", + "features.6.conv.0.0.weight: 0.6929\n", + "features.6.conv.1.0.weight: 0.6117\n", + "features.6.conv.2.weight: 0.7383\n", + "features.7.conv.0.0.weight: 0.5493\n", + "features.7.conv.1.0.weight: 0.3588\n", + "features.7.conv.2.weight: 0.6127\n", + "features.8.conv.0.0.weight: 0.8385\n", + "features.8.conv.1.0.weight: 0.7396\n", + "features.8.conv.2.weight: 0.8687\n", + "features.9.conv.0.0.weight: 0.8278\n", + "features.9.conv.1.0.weight: 0.7376\n", + "features.9.conv.2.weight: 0.8643\n", + "features.10.conv.0.0.weight: 0.8293\n", + "features.10.conv.1.0.weight: 0.7876\n", + "features.10.conv.2.weight: 0.8721\n", + "features.11.conv.0.0.weight: 0.7277\n", + "features.11.conv.1.0.weight: 0.7995\n", + "features.11.conv.2.weight: 0.7729\n", + "features.12.conv.0.0.weight: 0.8823\n", + "features.12.conv.1.0.weight: 0.7951\n", + "features.12.conv.2.weight: 0.9053\n", + "features.13.conv.0.0.weight: 0.8716\n", + "features.13.conv.1.0.weight: 0.8135\n", + "features.13.conv.2.weight: 0.9115\n", + "features.14.conv.0.0.weight: 0.7872\n", + "features.14.conv.1.0.weight: 0.6908\n", + "features.14.conv.2.weight: 0.8274\n", + "features.15.conv.0.0.weight: 0.9449\n", + "features.15.conv.1.0.weight: 0.7853\n", + "features.15.conv.2.weight: 0.9563\n", + "features.16.conv.0.0.weight: 0.9238\n", + "features.16.conv.1.0.weight: 0.7931\n", + "features.16.conv.2.weight: 0.9572\n", + "features.17.conv.0.0.weight: 0.8772\n", + "features.17.conv.1.0.weight: 0.9105\n", + "features.17.conv.2.weight: 0.9512\n", + "features.18.0.weight: 0.9781\n", + "classifier.1.weight: 0.0000\n" + ] + } + ], + "source": [ + "for (name, layer) in get_prunable_layers(model):\n", + " print(f\"{name}.weight: {tensor_sparsity(layer.weight).item():.4f}\")" + ] + }, + { + "cell_type": "markdown", + "id": "00805b02", + "metadata": {}, + "source": [ + "Finally, export your model to ONNX." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "48fb7c0e", + "metadata": {}, + "outputs": [], + "source": [ + "save_dir = \"experiment-0\"\n", + "exporter = ModuleExporter(model, output_dir=save_dir)\n", + "exporter.export_pytorch(name=\"mobilenet_v2-sparse-beans.pth\")\n", + "exporter.export_onnx(torch.randn(1, 3, 224, 224), name=\"sparse-model.onnx\", convert_qat=True)" + ] + }, + { + "cell_type": "markdown", + "id": "7960612c", + "metadata": {}, + "source": [ + "## Wrap Up\n", + "\n", + "The resulting model is is 90% sparse and achieves validation accuracy of ~99% (vs the unoptimized dense model at ~99%) without much hyperparameter search.\n", + "\n", + "Key hyperparameter experiments you may want to run include:\n", + "- Learning rate\n", + "- Learning rate schedule\n", + "- Sparsity level\n", + "- Number of pruning epochs\n", + "\n", + "DeepSparse supports speedup from pruning and quantization. To reach maximum performance, check out our examples of quantizing a model!" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/integrations/torchvision/tutorials/docs-torchvision-sparsify-from-scratch-resnet50-beans.ipynb b/integrations/torchvision/tutorials/docs-torchvision-sparsify-from-scratch-resnet50-beans.ipynb new file mode 100644 index 00000000000..ab133807bec --- /dev/null +++ b/integrations/torchvision/tutorials/docs-torchvision-sparsify-from-scratch-resnet50-beans.ipynb @@ -0,0 +1,2059 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "00e081b7", + "metadata": {}, + "source": [ + "# Sparsifying ResNet-50 from Scratch (Beans)\n", + "\n", + "In this example, we will demonstrate how to sparsify an image classification model from scratch using SparseML's PyTorch integration. We train and prune [ResNet-50](https://pytorch.org/vision/main/models/generated/torchvision.models.resnet50.html) on the downstream [Beans dataset](https://huggingface.co/datasets/beans) using the Global Magnitude Pruning algorithm. \n", + "\n", + "## Agenda\n", + "\n", + "There are a few steps:\n", + "\n", + " 1. Setup the dataset\n", + " 2. Setup the PyTorch training loop\n", + " 3. Train a dense version of ResNet-50\n", + " 4. Run the GMP pruning algorithm on the dense model\n", + " \n", + "## Installation\n", + "\n", + "Install SparseML and `datasets` with `pip`:\n", + "\n", + "```\n", + "pip install sparseml[torchvision]\n", + "pip install datasets\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "1ad80edf", + "metadata": {}, + "outputs": [], + "source": [ + "import torch\n", + "import sparseml\n", + "import torchvision\n", + "from sparseml.pytorch.optim import ScheduledModifierManager\n", + "from sparseml.pytorch.utils import TensorBoardLogger, ModuleExporter, get_prunable_layers, tensor_sparsity\n", + "from torch.utils.data import DataLoader\n", + "from torch.nn import CrossEntropyLoss\n", + "from torch.optim import Adam\n", + "from torchvision import transforms\n", + "from tqdm.auto import tqdm\n", + "import math\n", + "import datasets" + ] + }, + { + "cell_type": "markdown", + "id": "c421a838", + "metadata": {}, + "source": [ + "## Step 1: Setup Dataset\n", + "\n", + "Beans leaf dataset is a set of images of diseased and healthy leaves. Based on a leaf image, the goal of this task is to predict the disease type (Angular Leaf Spot and Bean Rust), if any.\n", + "\n", + "We will use the Hugging Face `datasets` library to download the data and the torchvision `ImageFolder` in the training loop.\n", + "\n", + "[Checkout the dataset card](https://huggingface.co/datasets/beans)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3f49303e", + "metadata": {}, + "outputs": [], + "source": [ + "beans_dataset = datasets.load_dataset(\"beans\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "4115c9d8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/home/ubuntu/.cache/huggingface/datasets/downloads/extracted/7ad2d437b751e134577576a32849c44a9ade89297680ad5f6a64051e2108810b/train/angular_leaf_spot/angular_leaf_spot_train.0.jpg\n", + "/home/ubuntu/.cache/huggingface/datasets/downloads/extracted/1141f86479bc0bb56c75616d153591cc8299d1ea4edc53bb1ab65edd2c65b240/validation/angular_leaf_spot/angular_leaf_spot_val.0.jpg\n" + ] + } + ], + "source": [ + "print(beans_dataset[\"train\"][0][\"image_file_path\"])\n", + "print(beans_dataset[\"validation\"][0][\"image_file_path\"])" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "00aaf463", + "metadata": {}, + "outputs": [], + "source": [ + "train_path = \"/home/ubuntu/.cache/huggingface/datasets/downloads/extracted/7ad2d437b751e134577576a32849c44a9ade89297680ad5f6a64051e2108810b/train\"\n", + "val_path = \"/home/ubuntu/.cache/huggingface/datasets/downloads/extracted/1141f86479bc0bb56c75616d153591cc8299d1ea4edc53bb1ab65edd2c65b240/validation\"" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "7d180bbc", + "metadata": {}, + "outputs": [], + "source": [ + "NUM_LABELS = 3\n", + "BATCH_SIZE = 64\n", + "\n", + "# imagenet transforms\n", + "imagenet_transform = transforms.Compose([\n", + " transforms.Resize(size=256, interpolation=transforms.InterpolationMode.BILINEAR, max_size=None, antialias=None),\n", + " transforms.CenterCrop(size=(224, 224)),\n", + " transforms.ToTensor(),\n", + " transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n", + "])\n", + "\n", + "# datasets\n", + "train_dataset = torchvision.datasets.ImageFolder(\n", + " root=train_path,\n", + " transform=imagenet_transform\n", + ")\n", + "\n", + "val_dataset = torchvision.datasets.ImageFolder(\n", + " root=val_path,\n", + " transform=imagenet_transform\n", + ")\n", + "\n", + "\n", + "# dataloaders\n", + "train_loader = DataLoader(train_dataset, BATCH_SIZE, shuffle=True, pin_memory=True, num_workers=16)\n", + "val_loader = DataLoader(val_dataset, BATCH_SIZE, shuffle=False, pin_memory=True, num_workers=16)" + ] + }, + { + "cell_type": "markdown", + "id": "132fc514", + "metadata": {}, + "source": [ + "## Step 2: Setup PyTorch Training Loop\n", + "\n", + "We will use this training loop below. This is standard PyTorch functionality." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "5f1b878a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cuda\n" + ] + } + ], + "source": [ + "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n", + "print(device)\n", + "\n", + "def run_model_one_epoch(model, data_loader, criterion, device, train=False, optimizer=None):\n", + " if train:\n", + " model.train()\n", + " else:\n", + " model.eval()\n", + "\n", + " running_loss = 0.0\n", + " total_correct = 0\n", + " total_predictions = 0\n", + "\n", + " # loop through batches\n", + " for step, (inputs, labels) in tqdm(enumerate(data_loader), total=len(data_loader)):\n", + " inputs = inputs.to(device)\n", + " labels = labels.to(device)\n", + "\n", + " if train:\n", + " optimizer.zero_grad()\n", + "\n", + " # compute loss, run backpropogation\n", + " outputs = model(inputs) # model returns logits\n", + " loss = criterion(outputs, labels)\n", + " if train:\n", + " loss.backward()\n", + " optimizer.step()\n", + "\n", + " running_loss += loss.item()\n", + "\n", + " # run evaluation\n", + " predictions = outputs.argmax(dim=1)\n", + " total_correct += torch.sum(predictions == labels).item()\n", + " total_predictions += inputs.size(0)\n", + "\n", + " # return loss and evaluation metric\n", + " loss = running_loss / (step + 1.0)\n", + " accuracy = total_correct / total_predictions\n", + " return loss, accuracy" + ] + }, + { + "cell_type": "markdown", + "id": "21e250c6", + "metadata": {}, + "source": [ + "## **Step 3: Train ResNet-50 on Beans**\n", + "\n", + "First, we will train a dense version of ResNet-50 on the Beans dataset." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "4d554578", + "metadata": {}, + "outputs": [], + "source": [ + "# download pre-trained model, setup classification head\n", + "model = torchvision.models.resnet50(weights=torchvision.models.ResNet50_Weights.DEFAULT)\n", + "model.fc = torch.nn.Linear(model.fc.in_features, NUM_LABELS)\n", + "model.to(device)\n", + "\n", + "# setup loss function and optimizer\n", + "criterion = CrossEntropyLoss()\n", + "optimizer = Adam(model.parameters(), lr=8e-3) # lr will be override by sparseml" + ] + }, + { + "cell_type": "markdown", + "id": "39a82a98", + "metadata": {}, + "source": [ + "Next, we will use SparseML's recipes to set the hyperparameters of training loop. In this case, we will use the following recipe:\n", + "\n", + "```yaml\n", + "# Epoch and Learning-Rate variables\n", + "num_epochs: 10.0\n", + "init_lr: 0.0005\n", + "\n", + "training_modifiers:\n", + " - !EpochRangeModifier\n", + " start_epoch: 0.0\n", + " end_epoch: eval(num_epochs)\n", + "\n", + " - !LearningRateFunctionModifier\n", + " final_lr: 0.0\n", + " init_lr: eval(init_lr)\n", + " lr_func: cosine\n", + " start_epoch: 0.0\n", + " end_epoch: eval(num_epochs)\n", + "```\n", + "\n", + "As you can see, the recipe includes an `!EpochRangeModifier` and a `!LearningRateFunctionModifier`. These modifiers simply set the number of epochs to train for and the learning rate schedule. As a result, the final model will be dense." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d4553beb", + "metadata": {}, + "outputs": [], + "source": [ + "!cat ./recipes/resnet50-beans-dense-recipe.yaml" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "1b19a8d8", + "metadata": {}, + "outputs": [], + "source": [ + "dense_recipe_path = \"./recipes/resnet50-beans-dense-recipe.yaml\"" + ] + }, + { + "cell_type": "markdown", + "id": "9e00a7a9", + "metadata": {}, + "source": [ + "Next, we use SparseML's `ScheduledModifierManager` to parse and apply the recipe. The `manager.modify` function modifies and wraps the `model` and `optimizer` with the instructions from the recipe. You can use the `model` and `optimizer` just like standard PyTorch objects." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "1749e00d", + "metadata": {}, + "outputs": [], + "source": [ + "# create ScheduledModifierManager and Optimizer wrapper\n", + "manager = ScheduledModifierManager.from_yaml(dense_recipe_path)\n", + "optimizer = manager.modify(model, optimizer, steps_per_epoch=len(train_loader))" + ] + }, + { + "cell_type": "markdown", + "id": "f3b56352", + "metadata": {}, + "source": [ + "Kick off the transfer learning loop. Our run reached ~99% validation accuracy after 10 epochs." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "d00d175b", + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running Training Epoch 1/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d5b96520239d4d728d23a4f099eb8fd3", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 1/10\n", + "Training Loss: 0.45206236138063316\n", + "Top 1 Acc: 0.8085106382978723\n", + "\n", + "Running Validation Epoch 1/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "287feebeb9514f33b58e0cb6a825f672", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 1/10\n", + "Val Loss: 0.8609340712428093\n", + "Top 1 Acc: 0.849624060150376\n", + "\n", + "Running Training Epoch 2/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "76336e81f4c24749b17ca07b2ce5bd69", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 2/10\n", + "Training Loss: 0.1085617478717776\n", + "Top 1 Acc: 0.9584139264990329\n", + "\n", + "Running Validation Epoch 2/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c34d773bae5c48ce96743bd2b807a6f7", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 2/10\n", + "Val Loss: 0.1460044514387846\n", + "Top 1 Acc: 0.9699248120300752\n", + "\n", + "Running Training Epoch 3/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "aa655dafb1514e9684fd3d949effd615", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 3/10\n", + "Training Loss: 0.07007143213687574\n", + "Top 1 Acc: 0.97678916827853\n", + "\n", + "Running Validation Epoch 3/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d4c8ea7aa9d04edea382c7f14a03a065", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 3/10\n", + "Val Loss: 0.027990046694564324\n", + "Top 1 Acc: 0.9849624060150376\n", + "\n", + "Running Training Epoch 4/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "34da8fe5ac4a48d584517b9861c6965b", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 4/10\n", + "Training Loss: 0.017229604699155864\n", + "Top 1 Acc: 0.9970986460348162\n", + "\n", + "Running Validation Epoch 4/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1f06331bc3a3451f8220574fa627d139", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 4/10\n", + "Val Loss: 0.024875935167074203\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Training Epoch 5/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ecbbd1253c8c474d9822ca9aa3f32358", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 5/10\n", + "Training Loss: 0.0032389334005796734\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Validation Epoch 5/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "9a3cd1a358764830b5b657cc77f2c57c", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 5/10\n", + "Val Loss: 0.020098081634690363\n", + "Top 1 Acc: 0.9849624060150376\n", + "\n", + "Running Training Epoch 6/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "e454370d9ac948c9ac2015297a578ff6", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 6/10\n", + "Training Loss: 0.0009401099643368713\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Validation Epoch 6/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "e881bba812114c39a09b3341efc5a4ae", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 6/10\n", + "Val Loss: 0.013677676247122387\n", + "Top 1 Acc: 0.9924812030075187\n", + "\n", + "Running Training Epoch 7/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1bdc58cad336471580d42b9c869f8379", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 7/10\n", + "Training Loss: 0.0007901448304491008\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Validation Epoch 7/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "071da6885f4644f4abb9e3c68850ea07", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 7/10\n", + "Val Loss: 0.011986067402176559\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Training Epoch 8/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "94495ac2721a4112b6b53b42ac16787c", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 8/10\n", + "Training Loss: 0.001196134924505125\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Validation Epoch 8/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c2a2315f371443c89e8492cadb9b98ae", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 8/10\n", + "Val Loss: 0.008087300811894238\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Training Epoch 9/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "e4cbaef71d224dcab1918a8e68738567", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 9/10\n", + "Training Loss: 0.0012429110587725196\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Validation Epoch 9/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "458f09dd3c004d65b683786268d2bce1", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 9/10\n", + "Val Loss: 0.01152486567540715\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Training Epoch 10/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "bd1541379cdd496b8fd93b8ced597067", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 10/10\n", + "Training Loss: 0.017825346116082715\n", + "Top 1 Acc: 0.9990328820116054\n", + "\n", + "Running Validation Epoch 10/10\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c952c716ba6d46d9919d29b05fd5b2df", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 10/10\n", + "Val Loss: 0.01295137139580523\n", + "Top 1 Acc: 0.9849624060150376\n", + "\n" + ] + } + ], + "source": [ + "# run transfer learning\n", + "epoch = 0\n", + "for epoch in range(manager.max_epochs):\n", + " # run training loop\n", + " epoch_name = f\"{epoch + 1}/{manager.max_epochs}\"\n", + " print(f\"Running Training Epoch {epoch_name}\")\n", + " train_loss, train_acc = run_model_one_epoch(model, train_loader, criterion, device, train=True, optimizer=optimizer)\n", + " print(f\"Training Epoch: {epoch_name}\\nTraining Loss: {train_loss}\\nTop 1 Acc: {train_acc}\\n\")\n", + "\n", + " # run validation loop\n", + " print(f\"Running Validation Epoch {epoch_name}\")\n", + " val_loss, val_acc = run_model_one_epoch(model, val_loader, criterion, device)\n", + " print(f\"Validation Epoch: {epoch_name}\\nVal Loss: {val_loss}\\nTop 1 Acc: {val_acc}\\n\")\n", + "\n", + "manager.finalize(model)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "11fa4cf2", + "metadata": {}, + "outputs": [], + "source": [ + "from sparseml.pytorch.utils import ModuleExporter\n", + "\n", + "save_dir = \"dense_model\"\n", + "exporter = ModuleExporter(model, output_dir=save_dir)\n", + "exporter.export_pytorch(name=\"resnet-50-dense-beans.pth\")" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "1617f476", + "metadata": {}, + "outputs": [], + "source": [ + "torch.cuda.empty_cache()" + ] + }, + { + "cell_type": "markdown", + "id": "848572dd", + "metadata": {}, + "source": [ + "## Step 4: Prune The Model\n", + "\n", + "With a model trained on Beans, we are now ready to apply the GMP algorithm to prune the model. The GMP algorithm is an interative pruning algorithm. At the end of each epoch, we identify the lowest magnitude weights (those closest to 0) and remove them from the network starting from an initial level of sparsity until a final level of sparsity. The remaining nonzero weights are then fine-tuned onto training dataset." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "8447d074", + "metadata": {}, + "outputs": [], + "source": [ + "checkpoint = torch.load(\"./dense_model/training/resnet-50-dense-beans.pth\")\n", + "model = torchvision.models.resnet50()\n", + "model.fc = torch.nn.Linear(model.fc.in_features, NUM_LABELS)\n", + "model.load_state_dict(checkpoint['state_dict'])\n", + "model.to(device)\n", + "\n", + "# setup loss function and optimizer, LR will be overriden by sparseml\n", + "criterion = CrossEntropyLoss()\n", + "optimizer = Adam(model.parameters(), lr=8e-3)" + ] + }, + { + "cell_type": "markdown", + "id": "edb62dc9", + "metadata": { + "scrolled": false + }, + "source": [ + "Next, we need to create a SparseML recipe which includes the GMP algorithm. The `!GlobalMagnitudePruningModifier` modifier instructs SparseML to apply the GMP algorithm at a global level (pruning the lowest magnitude weights across all layers).\n", + "\n", + "Firstly, we need to decide identify which parameters of the model to apply the GMP algorithm to. We can use the `get_prunable_layers` function to inspect:" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "8950185f", + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "conv1\n", + "layer1.0.conv1\n", + "layer1.0.conv2\n", + "layer1.0.conv3\n", + "layer1.0.downsample.0\n", + "layer1.1.conv1\n", + "layer1.1.conv2\n", + "layer1.1.conv3\n", + "layer1.2.conv1\n", + "layer1.2.conv2\n", + "layer1.2.conv3\n", + "layer2.0.conv1\n", + "layer2.0.conv2\n", + "layer2.0.conv3\n", + "layer2.0.downsample.0\n", + "layer2.1.conv1\n", + "layer2.1.conv2\n", + "layer2.1.conv3\n", + "layer2.2.conv1\n", + "layer2.2.conv2\n", + "layer2.2.conv3\n", + "layer2.3.conv1\n", + "layer2.3.conv2\n", + "layer2.3.conv3\n", + "layer3.0.conv1\n", + "layer3.0.conv2\n", + "layer3.0.conv3\n", + "layer3.0.downsample.0\n", + "layer3.1.conv1\n", + "layer3.1.conv2\n", + "layer3.1.conv3\n", + "layer3.2.conv1\n", + "layer3.2.conv2\n", + "layer3.2.conv3\n", + "layer3.3.conv1\n", + "layer3.3.conv2\n", + "layer3.3.conv3\n", + "layer3.4.conv1\n", + "layer3.4.conv2\n", + "layer3.4.conv3\n", + "layer3.5.conv1\n", + "layer3.5.conv2\n", + "layer3.5.conv3\n", + "layer4.0.conv1\n", + "layer4.0.conv2\n", + "layer4.0.conv3\n", + "layer4.0.downsample.0\n", + "layer4.1.conv1\n", + "layer4.1.conv2\n", + "layer4.1.conv3\n", + "layer4.2.conv1\n", + "layer4.2.conv2\n", + "layer4.2.conv3\n", + "fc\n" + ] + } + ], + "source": [ + "# print parameters\n", + "for (name, layer) in get_prunable_layers(model):\n", + " print(f\"{name}\")" + ] + }, + { + "cell_type": "markdown", + "id": "f5ef3bdf", + "metadata": {}, + "source": [ + "We will apply pruning to each of the convs and exclude the fc layer (which is the final projection head). Fortunately, SparseML allows us to pass regexes to identify layers in the network, so we can use the following list to identify the relevant layers for pruning:\n", + " \n", + " - 'conv1.weight'\n", + " - 're:layer1.*.conv1.weight'\n", + " - 're:layer1.*.conv2.weight'\n", + " - 're:layer1.*.conv3.weight'\n", + " - 're:layer1.0.downsample.0.weight'\n", + " - 're:layer2.*.conv1.weight'\n", + " - 're:layer2.*.conv2.weight'\n", + " - 're:layer2.*.conv3.weight'\n", + " - 're:layer2.0.downsample.0.weight'\n", + " - 're:layer3.*.conv1.weight'\n", + " - 're:layer3.*.conv2.weight'\n", + " - 're:layer3.*.conv3.weight'\n", + " - 're:layer3.0.downsample.0.weight'\n", + " - 're:layer4.*.conv1.weight'\n", + " - 're:layer4.*.conv2.weight'\n", + " - 're:layer4.*.conv3.weight'\n", + " - 're:layer4.0.downsample.0.weight'\n", + "\n", + "Here is what the recipe looks like:\n", + "\n", + "```yaml\n", + "# Epoch hyperparams\n", + "stabilization_epochs: 1.0\n", + "pruning_epochs: 9.0\n", + "finetuning_epochs: 5.0\n", + "\n", + "# Learning rate hyperparams\n", + "init_lr: 0.0001\n", + "final_lr: 0.00005\n", + "\n", + "# Pruning hyperparams\n", + "init_sparsity: 0.05\n", + "final_sparsity: 0.9\n", + "\n", + "# Stabalization Stage\n", + "training_modifiers:\n", + " - !EpochRangeModifier\n", + " start_epoch: 0.0\n", + " end_epoch: eval(stabilization_epochs + pruning_epochs + finetuning_epochs)\n", + " \n", + " - !SetLearningRateModifier\n", + " start_epoch: 0.0\n", + " learning_rate: eval(init_lr)\n", + "\n", + "# Pruning Stage\n", + "pruning_modifiers:\n", + " - !LearningRateFunctionModifier\n", + " init_lr: eval(init_lr)\n", + " final_lr: eval(final_lr)\n", + " lr_func: cosine\n", + " start_epoch: eval(stabilization_epochs)\n", + " end_epoch: eval(stabilization_epochs + pruning_epochs)\n", + " \n", + " - !GlobalMagnitudePruningModifier\n", + " init_sparsity: eval(init_sparsity)\n", + " final_sparsity: eval(final_sparsity)\n", + " start_epoch: eval(stabilization_epochs)\n", + " end_epoch: eval(stabilization_epochs + pruning_epochs)\n", + " update_frequency: 0.5\n", + " params: \n", + " - 'conv1.weight'\n", + " - 're:layer1.*.conv1.weight'\n", + " - 're:layer1.*.conv2.weight'\n", + " - 're:layer1.*.conv3.weight'\n", + " - 're:layer1.0.downsample.0.weight'\n", + " - 're:layer2.*.conv1.weight'\n", + " - 're:layer2.*.conv2.weight'\n", + " - 're:layer2.*.conv3.weight'\n", + " - 're:layer2.0.downsample.0.weight'\n", + " - 're:layer3.*.conv1.weight'\n", + " - 're:layer3.*.conv2.weight'\n", + " - 're:layer3.*.conv3.weight'\n", + " - 're:layer3.0.downsample.0.weight'\n", + " - 're:layer4.*.conv1.weight'\n", + " - 're:layer4.*.conv2.weight'\n", + " - 're:layer4.*.conv3.weight'\n", + " - 're:layer4.0.downsample.0.weight'\n", + " leave_enabled: True\n", + "\n", + "# Finetuning Stage\n", + "finetuning_modifiers:\n", + " - !LearningRateFunctionModifier\n", + " init_lr: eval(init_lr)\n", + " final_lr: eval(final_lr)\n", + " lr_func: cosine\n", + " start_epoch: eval(stabilization_epochs + pruning_epochs)\n", + " end_epoch: eval(stabilization_epochs + pruning_epochs + finetuning_epochs) \n", + "```\n", + "\n", + "This recipe specifies that we will run the GMP algorithm for 9 epochs after running one warmup epoch. We start at an init_sparsity level of 5% and gradually increase sparsity to a final_sparsity level of 90% following a cubic curve. The pruning is applied in an unstructured manner, meaning that any weight can be pruned.\n", + "\n", + "Over the final 5 epochs, we will fine-tune the 90% pruned model further. Since we set leave_enabled=True the sparsity level will be maintained as the fine-tuning occurs." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0c492e33", + "metadata": {}, + "outputs": [], + "source": [ + "!cat recipes/resnet50-beans-pruning-recipe.yaml" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "9cc0e8ab", + "metadata": {}, + "outputs": [], + "source": [ + "pruning_recipe_path = \"./recipes/resnet50-beans-pruning-recipe.yaml\"" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "68646bc7", + "metadata": {}, + "outputs": [], + "source": [ + "# create ScheduledModifierManager and Optimizer wrapper\n", + "manager = ScheduledModifierManager.from_yaml(pruning_recipe_path)\n", + "logger = TensorBoardLogger(log_path=\"./tensorboard_outputs\")\n", + "optimizer = manager.modify(model, optimizer, loggers=[logger], steps_per_epoch=len(train_loader))" + ] + }, + { + "cell_type": "markdown", + "id": "1ab5b75b", + "metadata": {}, + "source": [ + "Next, kick off the GMP training loop. \n", + "\n", + "As you can see, we use the wrapped `optimizer` and `model` in the same way as above. SparseML parsed the recipe and updated the `optimizer` with the logic of GMP algorithm from the recipe. This allows you to just the `optimizer` and `model` as usual, with all of the pruning-related logic specified by the declarative recipe interface.\n", + "\n", + "Our 90% pruned model reaches ~99% validation accuracy (vs ~99% for the dense model)." + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "601c8c21", + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running Training Epoch 1/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1c7ce2fc1cfd45979ada8fa0b6fcf3e6", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 1/15\n", + "Training Loss: 0.00033969324495581747\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Validation Epoch 1/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "e3aef9e2789941b0ae700fde6e266376", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 1/15\n", + "Val Loss: 0.013618851000501309\n", + "Top 1 Acc: 0.9849624060150376\n", + "\n", + "Running Training Epoch 2/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "fffd99128b11403f9b57011320732c16", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 2/15\n", + "Training Loss: 9.199756892913309e-05\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Validation Epoch 2/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "e328d77edeb4431e90201713fdb617dd", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 2/15\n", + "Val Loss: 0.025973695794164087\n", + "Top 1 Acc: 0.9849624060150376\n", + "\n", + "Running Training Epoch 3/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "2e68e294bf494959be7e44222cfca3ae", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 3/15\n", + "Training Loss: 0.0006384848421235159\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Validation Epoch 3/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "13a6a67a5ccf49468cc98169c5b425a8", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 3/15\n", + "Val Loss: 0.0031044411274100034\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Training Epoch 4/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "db7f16560b2044a5b7bf4b99684ccaba", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 4/15\n", + "Training Loss: 0.0006065369069641319\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Validation Epoch 4/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "a663816b9381480eb5f924efd32c8fd3", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 4/15\n", + "Val Loss: 0.002252104241051711\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Training Epoch 5/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "18df31a72edb49e4a1f1c747589bdac3", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 5/15\n", + "Training Loss: 0.031195201322963627\n", + "Top 1 Acc: 0.9990328820116054\n", + "\n", + "Running Validation Epoch 5/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "8bc095e5df214848a718235df4717e74", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 5/15\n", + "Val Loss: 0.01123013386192421\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Training Epoch 6/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1d08639063644773b61b000c5b1f2efe", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 6/15\n", + "Training Loss: 0.010756760572001119\n", + "Top 1 Acc: 0.9990328820116054\n", + "\n", + "Running Validation Epoch 6/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "68c1be15dc7d4af68ec6c19153f692f9", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 6/15\n", + "Val Loss: 0.07213001201550166\n", + "Top 1 Acc: 0.9924812030075187\n", + "\n", + "Running Training Epoch 7/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "1e97320b9902466ea5c3c4eae6bdf9a2", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 7/15\n", + "Training Loss: 0.026524252669118783\n", + "Top 1 Acc: 0.9970986460348162\n", + "\n", + "Running Validation Epoch 7/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "3ce2e377d4dc4cc79f0f486ba85cee39", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 7/15\n", + "Val Loss: 0.177118182182312\n", + "Top 1 Acc: 0.9774436090225563\n", + "\n", + "Running Training Epoch 8/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "a49d19cebfea407eac41f8f48f1026ce", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 8/15\n", + "Training Loss: 0.02232004324083819\n", + "Top 1 Acc: 0.9990328820116054\n", + "\n", + "Running Validation Epoch 8/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7a76f59cc2944c69b531baf0f07bd609", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 8/15\n", + "Val Loss: 0.10358777642250061\n", + "Top 1 Acc: 0.9699248120300752\n", + "\n", + "Running Training Epoch 9/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f5ebb79fa89345a7ae603be67cbe179b", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 9/15\n", + "Training Loss: 0.029385707779403997\n", + "Top 1 Acc: 0.9990328820116054\n", + "\n", + "Running Validation Epoch 9/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "33b7f4317a3d42d0b7baa010ebc2bdcb", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 9/15\n", + "Val Loss: 0.042455013220508896\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Training Epoch 10/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "dbdb5527e3684766bc7015ff58bdce55", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 10/15\n", + "Training Loss: 0.007427054580629748\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Validation Epoch 10/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b73a0d01704c495e90d46ce5b418ae3b", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 10/15\n", + "Val Loss: 0.020314963534474373\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Training Epoch 11/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d48f532ce1fe443986390a95d10a214a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 11/15\n", + "Training Loss: 0.005854974952800309\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Validation Epoch 11/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "66decd3b06e14086a29442a5dc339bce", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 11/15\n", + "Val Loss: 0.013980435362706581\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Training Epoch 12/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "761dd586eea2462d8059642a6fa01861", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 12/15\n", + "Training Loss: 0.002781623138991349\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Validation Epoch 12/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "ef312ea80a14430ebfc5367acbb70d52", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 12/15\n", + "Val Loss: 0.011425975399712721\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Training Epoch 13/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "322dec36498c44a3ae953f2ea2364734", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 13/15\n", + "Training Loss: 0.004056999764596934\n", + "Top 1 Acc: 0.9990328820116054\n", + "\n", + "Running Validation Epoch 13/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7a431075ae9345cf894e5aa41a086257", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 13/15\n", + "Val Loss: 0.013013879070058465\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Training Epoch 14/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "67fa6ab896e945b2a29e27f361e6075a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 14/15\n", + "Training Loss: 0.002845817831043592\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Validation Epoch 14/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7e16741614424bb3b4ae46bc60ca99ea", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 14/15\n", + "Val Loss: 0.010720587490747372\n", + "Top 1 Acc: 1.0\n", + "\n", + "Running Training Epoch 15/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "bb350d3d25914b7cbc88a2c642abbd3d", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/17 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Epoch: 15/15\n", + "Training Loss: 0.009813380410538657\n", + "Top 1 Acc: 0.9980657640232108\n", + "\n", + "Running Validation Epoch 15/15\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "bc2e3959fb7945ef821b9c58291bdff6", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + " 0%| | 0/3 [00:00, ?it/s]" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Validation Epoch: 15/15\n", + "Val Loss: 0.011411373193065325\n", + "Top 1 Acc: 1.0\n", + "\n" + ] + } + ], + "source": [ + "# run GMP algorithm\n", + "epoch = 0\n", + "for epoch in range(manager.max_epochs):\n", + " # run training loop\n", + " epoch_name = f\"{epoch + 1}/{manager.max_epochs}\"\n", + " print(f\"Running Training Epoch {epoch_name}\")\n", + " train_loss, train_acc = run_model_one_epoch(model, train_loader, criterion, device, train=True, optimizer=optimizer)\n", + " print(f\"Training Epoch: {epoch_name}\\nTraining Loss: {train_loss}\\nTop 1 Acc: {train_acc}\\n\")\n", + "\n", + " # run validation loop\n", + " print(f\"Running Validation Epoch {epoch_name}\")\n", + " val_loss, val_acc = run_model_one_epoch(model, val_loader, criterion, device)\n", + " print(f\"Validation Epoch: {epoch_name}\\nVal Loss: {val_loss}\\nTop 1 Acc: {val_acc}\\n\")\n", + " \n", + " logger.log_scalar(\"Metrics/Loss (Train)\", train_loss, epoch)\n", + " logger.log_scalar(\"Metrics/Accuracy (Train)\", train_acc, epoch)\n", + " logger.log_scalar(\"Metrics/Loss (Validation)\", val_loss, epoch)\n", + " logger.log_scalar(\"Metrics/Accuracy (Validation)\", val_acc, epoch)\n", + " \n", + "manager.finalize(model)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "65fb7b12", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "conv1.weight: 0.4039\n", + "layer1.0.conv1.weight: 0.4758\n", + "layer1.0.conv2.weight: 0.6846\n", + "layer1.0.conv3.weight: 0.5506\n", + "layer1.0.downsample.0.weight: 0.5157\n", + "layer1.1.conv1.weight: 0.5690\n", + "layer1.1.conv2.weight: 0.6410\n", + "layer1.1.conv3.weight: 0.5604\n", + "layer1.2.conv1.weight: 0.5430\n", + "layer1.2.conv2.weight: 0.6075\n", + "layer1.2.conv3.weight: 0.6064\n", + "layer2.0.conv1.weight: 0.5498\n", + "layer2.0.conv2.weight: 0.7556\n", + "layer2.0.conv3.weight: 0.6881\n", + "layer2.0.downsample.0.weight: 0.8303\n", + "layer2.1.conv1.weight: 0.7918\n", + "layer2.1.conv2.weight: 0.8089\n", + "layer2.1.conv3.weight: 0.7450\n", + "layer2.2.conv1.weight: 0.7564\n", + "layer2.2.conv2.weight: 0.8100\n", + "layer2.2.conv3.weight: 0.7706\n", + "layer2.3.conv1.weight: 0.7239\n", + "layer2.3.conv2.weight: 0.7862\n", + "layer2.3.conv3.weight: 0.7415\n", + "layer3.0.conv1.weight: 0.6814\n", + "layer3.0.conv2.weight: 0.8697\n", + "layer3.0.conv3.weight: 0.7558\n", + "layer3.0.downsample.0.weight: 0.9209\n", + "layer3.1.conv1.weight: 0.8875\n", + "layer3.1.conv2.weight: 0.9177\n", + "layer3.1.conv3.weight: 0.8482\n", + "layer3.2.conv1.weight: 0.9054\n", + "layer3.2.conv2.weight: 0.9143\n", + "layer3.2.conv3.weight: 0.8672\n", + "layer3.3.conv1.weight: 0.8686\n", + "layer3.3.conv2.weight: 0.9209\n", + "layer3.3.conv3.weight: 0.8573\n", + "layer3.4.conv1.weight: 0.8710\n", + "layer3.4.conv2.weight: 0.9158\n", + "layer3.4.conv3.weight: 0.8599\n", + "layer3.5.conv1.weight: 0.8293\n", + "layer3.5.conv2.weight: 0.9191\n", + "layer3.5.conv3.weight: 0.8144\n", + "layer4.0.conv1.weight: 0.7612\n", + "layer4.0.conv2.weight: 0.9458\n", + "layer4.0.conv3.weight: 0.8048\n", + "layer4.0.downsample.0.weight: 0.9347\n", + "layer4.1.conv1.weight: 0.9039\n", + "layer4.1.conv2.weight: 0.9626\n", + "layer4.1.conv3.weight: 0.8643\n", + "layer4.2.conv1.weight: 0.9441\n", + "layer4.2.conv2.weight: 0.9775\n", + "layer4.2.conv3.weight: 0.8976\n", + "fc.weight: 0.0000\n" + ] + } + ], + "source": [ + "for (name, layer) in get_prunable_layers(model):\n", + " print(f\"{name}.weight: {tensor_sparsity(layer.weight).item():.4f}\")" + ] + }, + { + "cell_type": "markdown", + "id": "00805b02", + "metadata": {}, + "source": [ + "Finally, export your model to ONNX." + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "417ac105", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/ubuntu/rshaw/sparseml/env/lib/python3.10/site-packages/torch/onnx/utils.py:439: UserWarning: It is recommended that constant folding be turned off ('do_constant_folding=False') when exporting the model in training-amenable mode, i.e. with 'training=TrainingMode.TRAIN' or 'training=TrainingMode.PRESERVE' (when model is in training mode). Otherwise, some learnable model parameters may not translate correctly in the exported ONNX model because constant folding mutates model parameters. Please consider turning off constant folding or setting the training=TrainingMode.EVAL.\n", + " warnings.warn(\n" + ] + } + ], + "source": [ + "save_dir = \"experiment-0\"\n", + "exporter = ModuleExporter(model, output_dir=save_dir)\n", + "exporter.export_pytorch(name=\"resnet-50-sparse-beans.pth\")\n", + "exporter.export_onnx(torch.randn(1, 3, 224, 224), name=\"sparse-model.onnx\", convert_qat=True)" + ] + }, + { + "cell_type": "markdown", + "id": "7960612c", + "metadata": {}, + "source": [ + "## Wrap Up\n", + "\n", + "The resulting model is is 90% sparse and achieves validation accuracy of ~100% (vs the unoptimized dense model at ~99%) without much hyperparameter search.\n", + "\n", + "Key hyperparameter experiments you may want to run include:\n", + "- Learning rate\n", + "- Learning rate schedule\n", + "- Sparsity level\n", + "- Number of pruning epochs\n", + "\n", + "DeepSparse supports speedup from pruning and quantization. To reach maximum performance, check out our examples of quantizing a model!" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/integrations/torchvision/tutorials/recipes/mobilenetv2-beans-dense-recipe.yaml b/integrations/torchvision/tutorials/recipes/mobilenetv2-beans-dense-recipe.yaml new file mode 100644 index 00000000000..cd66d90908f --- /dev/null +++ b/integrations/torchvision/tutorials/recipes/mobilenetv2-beans-dense-recipe.yaml @@ -0,0 +1,16 @@ + +# Epoch and Learning-Rate variables +num_epochs: 10.0 +init_lr: 0.0005 + +training_modifiers: + - !EpochRangeModifier + start_epoch: 0.0 + end_epoch: eval(num_epochs) + + - !LearningRateFunctionModifier + final_lr: 0.0 + init_lr: eval(init_lr) + lr_func: cosine + start_epoch: 0.0 + end_epoch: eval(num_epochs) \ No newline at end of file diff --git a/integrations/torchvision/tutorials/recipes/mobilenetv2-beans-pruning-recipe.yaml b/integrations/torchvision/tutorials/recipes/mobilenetv2-beans-pruning-recipe.yaml new file mode 100644 index 00000000000..68260e3c701 --- /dev/null +++ b/integrations/torchvision/tutorials/recipes/mobilenetv2-beans-pruning-recipe.yaml @@ -0,0 +1,53 @@ +# Epoch hyperparams +stabilization_epochs: 1.0 +pruning_epochs: 9.0 +finetuning_epochs: 5.0 + +# Learning rate hyperparams +init_lr: 0.0005 +final_lr: 0.00025 + +# Pruning hyperparams +init_sparsity: 0.05 +final_sparsity: 0.9 + +# Stabalization Stage +training_modifiers: + - !EpochRangeModifier + start_epoch: 0.0 + end_epoch: eval(stabilization_epochs + pruning_epochs + finetuning_epochs) + + - !SetLearningRateModifier + start_epoch: 0.0 + learning_rate: eval(init_lr) + +# Pruning Stage +pruning_modifiers: + - !LearningRateFunctionModifier + init_lr: eval(init_lr) + final_lr: eval(final_lr) + lr_func: cosine + start_epoch: eval(stabilization_epochs) + end_epoch: eval(stabilization_epochs + pruning_epochs) + + - !GlobalMagnitudePruningModifier + init_sparsity: eval(init_sparsity) + final_sparsity: eval(final_sparsity) + start_epoch: eval(stabilization_epochs) + end_epoch: eval(stabilization_epochs + pruning_epochs) + update_frequency: 0.5 + params: + - 'features.0.0.weight' + - 'features.18.0.weight' + - 're:features.*.conv.*.weight' + - 're:features.*.conv.*.*.weight' + leave_enabled: True + +# Finetuning Stage +finetuning_modifiers: + - !LearningRateFunctionModifier + init_lr: eval(init_lr) + final_lr: eval(final_lr) + lr_func: cosine + start_epoch: eval(stabilization_epochs + pruning_epochs) + end_epoch: eval(stabilization_epochs + pruning_epochs + finetuning_epochs) \ No newline at end of file diff --git a/integrations/torchvision/tutorials/recipes/resnet50-beans-dense-recipe.yaml b/integrations/torchvision/tutorials/recipes/resnet50-beans-dense-recipe.yaml new file mode 100644 index 00000000000..cd66d90908f --- /dev/null +++ b/integrations/torchvision/tutorials/recipes/resnet50-beans-dense-recipe.yaml @@ -0,0 +1,16 @@ + +# Epoch and Learning-Rate variables +num_epochs: 10.0 +init_lr: 0.0005 + +training_modifiers: + - !EpochRangeModifier + start_epoch: 0.0 + end_epoch: eval(num_epochs) + + - !LearningRateFunctionModifier + final_lr: 0.0 + init_lr: eval(init_lr) + lr_func: cosine + start_epoch: 0.0 + end_epoch: eval(num_epochs) \ No newline at end of file diff --git a/integrations/torchvision/tutorials/recipes/resnet50-beans-pruning-recipe.yaml b/integrations/torchvision/tutorials/recipes/resnet50-beans-pruning-recipe.yaml new file mode 100644 index 00000000000..bf63be0fd89 --- /dev/null +++ b/integrations/torchvision/tutorials/recipes/resnet50-beans-pruning-recipe.yaml @@ -0,0 +1,66 @@ +# Epoch hyperparams +stabilization_epochs: 1.0 +pruning_epochs: 9.0 +finetuning_epochs: 5.0 + +# Learning rate hyperparams +init_lr: 0.0001 +final_lr: 0.00005 + +# Pruning hyperparams +init_sparsity: 0.05 +final_sparsity: 0.9 + +# Stabalization Stage +training_modifiers: + - !EpochRangeModifier + start_epoch: 0.0 + end_epoch: eval(stabilization_epochs + pruning_epochs + finetuning_epochs) + + - !SetLearningRateModifier + start_epoch: 0.0 + learning_rate: eval(init_lr) + +# Pruning Stage +pruning_modifiers: + - !LearningRateFunctionModifier + init_lr: eval(init_lr) + final_lr: eval(final_lr) + lr_func: cosine + start_epoch: eval(stabilization_epochs) + end_epoch: eval(stabilization_epochs + pruning_epochs) + + - !GlobalMagnitudePruningModifier + init_sparsity: eval(init_sparsity) + final_sparsity: eval(final_sparsity) + start_epoch: eval(stabilization_epochs) + end_epoch: eval(stabilization_epochs + pruning_epochs) + update_frequency: 0.5 + params: + - 'conv1.weight' + - 're:layer1.*.conv1.weight' + - 're:layer1.*.conv2.weight' + - 're:layer1.*.conv3.weight' + - 're:layer1.0.downsample.0.weight' + - 're:layer2.*.conv1.weight' + - 're:layer2.*.conv2.weight' + - 're:layer2.*.conv3.weight' + - 're:layer2.0.downsample.0.weight' + - 're:layer3.*.conv1.weight' + - 're:layer3.*.conv2.weight' + - 're:layer3.*.conv3.weight' + - 're:layer3.0.downsample.0.weight' + - 're:layer4.*.conv1.weight' + - 're:layer4.*.conv2.weight' + - 're:layer4.*.conv3.weight' + - 're:layer4.0.downsample.0.weight' + leave_enabled: True + +# Finetuning Stage +finetuning_modifiers: + - !LearningRateFunctionModifier + init_lr: eval(init_lr) + final_lr: eval(final_lr) + lr_func: cosine + start_epoch: eval(stabilization_epochs + pruning_epochs) + end_epoch: eval(stabilization_epochs + pruning_epochs + finetuning_epochs) \ No newline at end of file diff --git a/integrations/torchvision/tutorials/sparse-transfer-learning.md b/integrations/torchvision/tutorials/sparse-transfer-learning.md new file mode 100644 index 00000000000..bc3e1ca7d22 --- /dev/null +++ b/integrations/torchvision/tutorials/sparse-transfer-learning.md @@ -0,0 +1,204 @@ + + +# Sparsifying Image Classification Models with the CLI + +This page explains how to fine-tune a pre-sparsified Torchvision image classification models like ResNet-50 with SparseML's CLI. + +## Sparse Transfer Learning Overview + +Sparse transfer learning is quite similiar to the typical transfer learning training, where we fine-tune a checkpoint pretrained on ImageNet onto a smaller downstream dataset. However, with Sparse Transfer Learning, we simply start the fine-tuning process from a pre-sparsified checkpoint and maintain sparsity while the training process occurs. + +SparseZoo contains pre-sparsified checkpoints for common image classification models like ResNet-50 and EfficientNet, which can be used as the starting checkpoints for the training process. + +[Check out the full list of pre-sparsified models](https://sparsezoo.neuralmagic.com/?domain=cv&sub_domain=classification&page=1) + +## Installation + +Install SparseML via `pip`. + +```bash +pip install sparseml[torchvision] +``` + +## Sparse Transfer Learning with ResNet-50 + +Let's try a simple example of Sparse Transfer Learning ResNet-50 onto [FastAI's Imagenette dataset](https://github.com/fastai/imagenette) (a subset of 10 easily classified classes from ImageNet). + +### Download Dataset + +Download Imagnette to your local directory: +```bash +wget https://s3.amazonaws.com/fast-ai-imageclas/imagenette2-320.tgz +tar -xvf imagenette2-320.tgz +``` + +### Kick off Training + +We will use SparseML's `sparseml.image_classification.train` training script. + +#### Transfer Learning Recipe + +To run sparse transfer learning, we first need to create/select a sparsification recipe. For sparse transfer, we need a recipe that instructs SparseML to maintain sparsity during training and to quantize the model over the final epochs. + +For ResNet-50, there is [premade transfer learning recipe available in SparseZoo](https://sparsezoo.neuralmagic.com/models/cv%2Fclassification%2Fresnet_v1-50%2Fpytorch%2Fsparseml%2Fimagenet%2Fpruned95_quant-none), identified by the following stub: +```bash +zoo:cv/classification/resnet_v1-50/pytorch/sparseml/imagenet/pruned95_quant-none?recipe_type=transfer-classification +``` + +Here's what the transfer learning recipe looks like: +```yaml +# Epoch and Learning-Rate variables +num_epochs: 10.0 +init_lr: 0.0005 + +# quantization variables +quantization_epochs: 6.0 + +training_modifiers: + - !EpochRangeModifier + start_epoch: 0.0 + end_epoch: eval(num_epochs) + + - !LearningRateFunctionModifier + final_lr: 0.0 + init_lr: eval(init_lr) + lr_func: cosine + start_epoch: 0.0 + end_epoch: eval(num_epochs) + +# Phase 1 Sparse Transfer Learning / Recovery +sparse_transfer_learning_modifiers: + - !ConstantPruningModifier + start_epoch: 0.0 + params: __ALL_PRUNABLE__ + +# Phase 2 Apply quantization +sparse_quantized_transfer_learning_modifiers: + - !QuantizationModifier + start_epoch: eval(num_epochs - quantization_epochs) +``` + +The "Modifiers" encode how SparseML should modify the training process for Sparse Transfer Learning: +- `ConstantPruningModifier` tells SparseML to pin weights at 0 over all epochs, maintaining the sparsity structure of the network +- `QuantizationModifier` tells SparseML to quantize the weights with quantization aware training over the last 6 epochs + +SparseML parses the instructions declared in the recipe and modifies the training loop accordingly before running the fine-tuning. + +#### Run the Training Loop + +Run the following to fine-tune the 95% pruned-quantized ResNet-50 on Imagenette. +```bash +sparseml.image_classification.train \ + --recipe zoo:cv/classification/resnet_v1-50/pytorch/sparseml/imagenet/pruned95_quant-none?recipe_type=transfer-classification \ + --checkpoint-path zoo:cv/classification/resnet_v1-50/pytorch/sparseml/imagenet/pruned95_quant-none?recipe_type=transfer-classification \ + --arch-key resnet50 \ + --dataset-path ./imagenette2-320\ + --batch-size 32 +``` + +Let's discuss the key arguments: +- `--checkpoint-path` specifies the starting model to use in the training process. It can either be a local path to a PyTorch checkpoint or a SparseZoo stub. Here, we passed a stub that identifies a 95% pruned-quantized version of ResNet-50 in the SparseZoo. The script downloads the PyTorch model to begin training. + +- `--arch-key` specifies the torchvision architecture of the checkpoint. For example, `resnet50` or `mobilenet`. + +- `--dataset-path` specifies the dataset used for training. We passed the local path to Imagenette. The dataset should be in the ImageFolder format (we will describe the format below). + +- `--recipe` specifies the transfer learning recipe. In this case, we passed a SparseZoo stub, which instructs SparseML to download a premade ResNet50 transfer learning recipe. In addition to SparseZoo stubs, you can also pass a local path to a YAML recipe. + +The script uses the SparseZoo stubs to identify and download the starting checkpoint and recipe file. SparseML then parses the transfer learning recipe and adjusts the training loop to maintain sparsity during the fine-tuning process. It then kicks off the transfer learning run. + +The resulting model is 95% pruned and quantized ResNet-50 trained on Imagenette! + +Run the help command to inspect the full list of arguments and configurations. +```bash +sparseml.image_classification.train --help +``` + +### Export to ONNX + +Run the following to export your model to ONNX for deployment with DeepSparse. + +```bash +sparseml.image_classification.export_onnx \ + --arch_key resnet50 \ + --checkpoint_path ./checkpoint.pth \ + --dataset-path ./imagenette2-320 +``` + +### Modify a Recipe + +To transfer learn this sparsified model to other datasets you may have to adjust certain hyperparameters in this recipe and/or training script. Some considerations: + +- For more complex datasets, increase the number of epochs, adjusting the learning rate step accordingly +- Adding more learning rate step milestones can lead to more jumps in accuracy +- Increase the learning rate when increasing batch size +- Increase the number of epochs if using SGD instead of the Adam optimizer +- Update the base learning rate based on the number of steps needed to train your dataset + +To update a recipe, you can download the YAML file from SparseZoo, make updates to the YAML directly, and pass the local path to SparseML. + +Alternatively, you can use `--recipe_args` to modify a recipe on the fly. The following runs for 15 epochs instead of 10: + +```bash +sparseml.image_classification.train \ + --recipe zoo:cv/classification/resnet_v1-50/pytorch/sparseml/imagenet/pruned95_quant-none?recipe_type=transfer-classification \ + --recipe_args '{"num_epochs": 15}' \ + --checkpoint-path zoo:cv/classification/resnet_v1-50/pytorch/sparseml/imagenet/pruned95_quant-none?recipe_type=transfer-classification \ + --arch-key resnet50 \ + --dataset-path ./imagenette2-320\ + --batch-size 32 +``` + +The `--recipe_args` are a json parsable dictionary of recipe variable names to values to overwrite the YAML-recipe. + +### Dataset Format + +SparseML's Torchvision CLI conforms to the [Torchvision ImageFolder dataset format](https://pytorch.org/vision/main/generated/torchvision.datasets.ImageFolder.html), where images are arranged into directories representing each class. To use a custom dataset with the SparseML CLI, you will need to arrange your data into this format. + +For example, the following downloads Imagenette to your local directory: + +```bash +wget https://s3.amazonaws.com/fast-ai-imageclas/imagenette2-320.tgz +tar -xvf imagenette2-320.tgz +``` + +The resulting `imagenette-320` directory looks like the following (where each subdirectory like `n01440764` +represents one of the 10 classes in the Imagenette dataset) and each `.JPEG` file is a training example. +```bash +|-train + |-n01440764 + |-n01440764_10026.JPEG + |-n01440764_10027.JPEG + |... + |-n02979186 + |-n03028079 + |-n03417042 + |-n03445777 + |-n02102040 + |-n03000684 + |-n03394916 + |-n03425413 + |-n03888257 +|-val + |-n01440764 + |-n02979186 + | ... +``` + +## Wrapping Up + +Checkout the DeepSparse repository for more information on deploying your sparse Image Classification models with DeepSparse for GPU class performance on CPUs. diff --git a/integrations/ultralytics-yolov5/README.md b/integrations/ultralytics-yolov5/README.md index effabf7bb8d..b06e715d0e1 100644 --- a/integrations/ultralytics-yolov5/README.md +++ b/integrations/ultralytics-yolov5/README.md @@ -20,7 +20,6 @@ This directory explains how to use SparseML's `ultralytics/yolov5` integration t There are two main workflows enabled by SparseML: - **Sparse Transfer Learning** - fine-tune a pre-sparsified YOLOv5 checkpoint on your own dataset **[RECOMMENDED]** - - **Sparsification from Scratch** - apply pruning and quantization to sparsify any YOLOv5 model from scratch Once trained, SparseML enables you to export models to the ONNX format, such that they can be deployed with DeepSparse.