<table class="fo-notebook-links" align="left">
    <td>
        <a target="_blank" href="https://colab.research.google.com/github/voxel51/fiftyone/blob/main/docs/source/tutorials/evaluate_classifications.ipynb">
            <img src="https://cdn.voxel51.com/colab-logo-256px.png"> &nbsp; Run in Google Colab
        </a>
    </td>
    <td>
        <a target="_blank" href="https://github.com/voxel51/fiftyone/blob/main/docs/source/tutorials/evaluate_classifications.ipynb">
            <img src="https://cdn.voxel51.com/github-logo-256px.png"> &nbsp; View source on GitHub
        </a>
    </td>
    <td>
        <a target="_blank" href="https://raw.githubusercontent.com/voxel51/fiftyone/main/docs/source/tutorials/evaluate_classifications.ipynb" download>
            <img src="https://cdn.voxel51.com/cloud-icon-256px.png"> &nbsp; Download notebook
        </a>
    </td>
</table>

# Evaluating a Classifier with FiftyOne

This notebook demonstrates an end-to-end example of fine-tuning a classification model [using fastai](https://github.com/fastai/fastai) on a [Kaggle dataset](https://www.kaggle.com/iarunava/cell-images-for-detecting-malaria) and using FiftyOne to evaluate it and understand the strengths and weaknesses of both the model and the underlying ground truth annotations.

Specifically, we’ll cover:

- Downloading the dataset via the [Kaggle API](https://github.com/Kaggle/kaggle-api)
- Loading the dataset [into FiftyOne](https://voxel51.com/docs/fiftyone/user_guide/import_datasets.html)
- Indexing the dataset by uniqueness using FiftyOne’s [uniqueness method](https://voxel51.com/docs/fiftyone/user_guide/brain.html#image-uniqueness) to identify interesting visual characteristics
- Fine-tuning a model on the dataset [using fastai](https://github.com/fastai/fastai)
- [Evaluating](https://voxel51.com/docs/fiftyone/user_guide/evaluation.html) the fine-tuned model using FiftyOne
- [Exporting](https://voxel51.com/docs/fiftyone/user_guide/export_datasets.html) the FiftyOne dataset for offline analysis

**So, what’s the takeaway?**

The loss function of your model training loop alone doesn’t give you the full picture of a model. In practice, the limiting factor on your model’s performance is often data quality issues that FiftyOne can help you address. In this notebook, we’ll cover:

- Viewing the *most unique* incorrect samples using FiftyOne’s [uniqueness method](https://voxel51.com/docs/fiftyone/user_guide/brain.html#image-uniqueness)
- Viewing the *hardest* incorrect predictions using FiftyOne’s [hardness method](https://voxel51.com/docs/fiftyone/user_guide/brain.html#sample-hardness)
- Identifying ground truth *mistakes* using FiftyOne’s [mistakenness method](https://voxel51.com/docs/fiftyone/user_guide/brain.html#label-mistakes)

Running the workflow presented here on your ML projects will help you to understand the current failure modes (edge cases) of your model and how to fix them, including:

- Identifying scenarios that require additional training samples in order to boost your model’s performance
- Deciding whether your ground truth annotations have errors/weaknesses that need to be corrected before any subsequent model training will be profitable

## Setup

If you haven’t already, install FiftyOne:

We’ll also need `torch` and `torchvision` installed:

## Download dataset

Let’s start by downloading the [Malaria Cell Images Dataset](https://www.kaggle.com/iarunava/cell-images-for-detecting-malaria) from Kaggle using the [Kaggle API](https://github.com/Kaggle/kaggle-api):

The unzipped dataset consists of a `cell_images/` folder with two subdirectories—`Uninfected` and `Parasitized`—that each contain 13782 example images of the respective class of this binary classification task:

## Load dataset into FiftyOne

Let’s load the dataset into [FiftyOne](https://voxel51.com/docs/fiftyone) and explore it!

### Create FiftyOne dataset

FiftyOne provides builtin support for loading datasets in [dozens of common formats](https://voxel51.com/docs/fiftyone/user_guide/import_datasets.html) with a single line of code:

### (Future use) Load an existing FiftyOne dataset

Now that the data is loaded into FiftyOne, you can easily [work with](https://voxel51.com/docs/fiftyone/user_guide/using_datasets.html) the same dataset in a future session on the same machine by loading it by name:

### Index the dataset by visual uniqueness

Let’s start by indexing the dataset by visual uniqueness using FiftyOne’s [image uniqueness method](https://voxel51.com/docs/fiftyone/user_guide/brain.html#image-uniqueness).

This method adds a scalar `uniqueness` field to each sample that measures the relative visual uniqueness of each sample compared to the other samples in the dataset.

### Visualize dataset in the App

Now let’s launch the [FiftyOne App](https://voxel51.com/docs/fiftyone/user_guide/app.html) and use it to interactively explore the dataset.

For example, try using the [view bar](https://voxel51.com/docs/fiftyone/user_guide/app.html#using-the-view-bar) to sort the samples so that we can view the *most visually unique* samples in the dataset:

Now let’s add a `Limit(500)` stage in the view bar and open the `Labels` tab to view some statistics about the 500 most unique samples in the dataset.

Notice that a vast majority of the most visually unique samples in the dataset are `Parasitized`, which makes sense because these are the infected, abnormal cells.

Conversely, if we use the view bar to show the 500 *least visually unique* samples, we find that 499 of them are `Uninfected`!

## Training a model

Now that we have some basic intuition about the dataset, let’s train a model!

In this example, we’ll use [fastai](https://github.com/fastai) to fine-tune a pre-trained model on our dataset in just a few lines of code and a few minutes of GPU time.

The code sample below loads the dataset into a fastai data loader:

Now let’s load a pre-trained [xresnet34 model](https://docs.fast.ai/vision.models.xresnet.html):

and fine-tune it for 15 epochs on our dataset:

In this case, we reached 96.2% validation accuracy in about 25 minutes!

Let’s preview some sample predictions using fastai:

### Save model checkpoint

Let’s save a checkpoint of our model so we can load it later.

If you’re working in a Colab notebook and would like to download your model, you can do so as follows:

### (Future use) Load saved model

Run this block if you would like to load a model that your previously trained and exported as a checkpoint.

For Colab users, run this first block to upload the checkpoint from your local machine:

fastai expects the model to be in a `models/` directory, so let’s move it:

Now we can load the saved model:

## Evaluating model with FiftyOne

While 96% accuracy sounds great, aggregate evaluation metrics are not enough to get a full understanding of the performance of a model and what needs to be done to further improve it.

### Add predictions to FiftyOne dataset

Let’s [add our model’s predictions](https://voxel51.com/docs/fiftyone/user_guide/using_datasets.html#labels) to our FiftyOne dataset so we can evaluate it in more detail:

The predictions are stored in a `predictions` field of our dataset:

We’ve added predictions for both the `train` split:

and the `validation` split:

### Running the evaluation

FiftyOne provides a powerful [evaluation API](https://voxel51.com/docs/fiftyone/user_guide/evaluation.html) for evaluating various types of models at the aggregate and sample-level.

In this case, we’ll use the [binary classification functionality](https://voxel51.com/docs/fiftyone/user_guide/evaluation.html#binary-evaluation) to analyze our model:

The method returned a `results` object that provides a number of convenient methods for analyzing our predictions.

### Viewing aggregate metrics

Let’s start by printing a classification report:

Now, how about a confusion matrix:

and finally a precision-recall curve:

The evaluation method also populated a new `eval` field on our samples that records whether each prediction is a true positive (TP), false positive (FP), false negative (FN), or true negative (TN).

In a few minutes, we’ll use this field to interactively explore each type of prediction visually in the App. But for now, let’s check the distribution of these labels:

### Visualizing the most unique predictions

Now that we have a sense for the aggregate performance of our model, let’s dive into sample-level analysis by loading a [dataset view](https://voxel51.com/docs/fiftyone/user_guide/using_views.html) in the App that shows the correctly predicted samples from the validation split, sorted in descending order by the visual uniqueness that we previously computed and stored in the `uniqueness` field of the dataset:

Now, things get more interesting when we update our view to show the most visually unique **INCORRECT** predictions from the validation split.

Note that some of these ground truth labels look questionable; it seems that some of our our ground truth annotations may need to be updated. We’ll investigate this more later.

### Compute sample hardness with FiftyOne

During training, it is useful to identify samples that are more difficult for a model to learn so that training can be more focused around these hard samples.

Let’s use FiftyOne’s [hardness method](https://voxel51.com/docs/fiftyone/user_guide/brain.html#sample-hardness) to index our dataset by the hardness of our predictions in the `predictions` field.

This method populates a scalar `hardness` field on each of our samples.

Now let’s use our hardness measure to view the **HARDEST FALSE POSITIVE** samples in the validation split of our dataset.

These are the failure modes of our current model, and this is where we need to dedicate our human time to understand what’s going on.

Here are some important questions to ask yourself:

- *Are any of the ground truth annotations on these samples incorrect?* If so, then correcting them will make the biggest positive impact on the ability of our model to separate these two classes
- *Are these predictions actually false positives?* If so, then adding more examples that are visually similar to these to your training dataset will also improve your model

Viewing the **HARDEST FALSE NEGATIVE** samples from the validation split also gives insights into what fools our model into wrongly believing that a sample is uninfected.

Or, are the ground truth annotations incorrect? The same questions from the previous section apply. Finding mistakes in your ground truth data is equally as important as identifying the true failure modes of your model.

### Finding ground truth mistakes using FiftyOne

Even well-known datasets can have [significant ground truth mistakes](https://towardsdatascience.com/i-performed-error-analysis-on-open-images-and-now-i-have-trust-issues-89080e03ba09).

Fortunately, FiftyOne provides a [mistakenness method](https://voxel51.com/docs/fiftyone/user_guide/brain.html#label-mistakes) that can automatically identify the potential ground truth mistakes in your dataset.

The cell below runs the mistakenness method using the predictions in the `predictions` field of the dataset as a point of reference to find the most likely mistakes in the `ground_truth` annotations:

We can easily update our view in the App to show, for example, the most likely annotation mistakes in the `train` split of our dataset. In the cell below, we have only selected the `eval` field in the App so that we see the samples together with their TP/FP/FN/TN evaluation labels.

I’m not a medical imaging expert, but to my untrained eye, the examples below suggest two concrete opportunities for improvement to our training dataset:

- Many of the false negatives below seem to be *true negatives*. These ground truth annotations likely need another annotation pass to correct for errors
- Many of the remaining false negatives seem to be cases where the infection is near the **boundary** of the cell images. Augmenting the training dataset with more `Parasitized` examples of this kind would likely improve the performance of our model!

## Export incorrect samples for further analysis

Now that we’ve identified some potential sources of annotation error, we can easily extract some aggregate analyses of the incorrect predictions:

The code sample below generates a JSON export of the 1042 samples in the dataset where the model generated false positive or false negative predictions:

This JSON file includes the filepaths for the raw images, so this file can be easily forwarded to your annotation team/vendor to complete a re-annotation pass.

If you’re working in a Colab notebook, you can download the errors JSON file to your machine as follows:

## Summary

In this notebook, we covered loading a dataset into FiftyOne, fine-tuning a fastai model on it, and analyzing the failure modes of the model using FiftyOne.

**So, what’s the takeaway?**

The loss function of your training loop doesn’t tell the whole story of your model; it’s critical to study the failure modes of your model so you can take the right actions to improve them.

In this notebook, we covered two types of actions:

- Finding potential annotation mistakes and exporting the problem samples for review/reannotation
- Identifying scenarios that require additional training samples

In upcoming tutorials, we’ll cover how FiftyOne can enable you to **automate** both of these actions. Stay tuned!

## Appendix A: Dataset export

FiftyOne provides native support for exporting datasets in [dozens of common formats](https://voxel51.com/docs/fiftyone/user_guide/export_datasets.html).

If you’re working in a notebook, you may want to export the *entire dataset*, including the additional analysis fields such as the `uniqueness`, `hardness`, `mistakenness`, and `eval` fields that we added in this tutorial. FiftyOne provides two simple options for this:

### Option 1: export without images

One option is to export only the labels (no raw images) in [JSON format](https://voxel51.com/docs/fiftyone/api/fiftyone.core.collections.html?highlight=write_json#fiftyone.core.collections.SampleCollection.write_json):

### Option 2: export with images

Alternatively, you can export the [entire dataset](https://voxel51.com/docs/fiftyone/user_guide/export_datasets.html#fiftyonedataset-export) (labels + images) as an archive:

You can [load an exported FiftyOne dataset](https://voxel51.com/docs/fiftyone/user_guide/import_datasets.html) back into FiftyOne in one line of code.

### Option 1: loading an export without images

If you exported only the labels (no raw images) in [JSON format](https://voxel51.com/docs/fiftyone/api/fiftyone.core.collections.html?highlight=write_json#fiftyone.core.collections.SampleCollection.write_json), you can reload the dataset into any environment that contains the raw images as follows:

### Option 2: loading an export with images

If you exported the [entire dataset](https://voxel51.com/docs/fiftyone/user_guide/import_datasets.html#FiftyOneDataset-import) (images + labels) then you can reload the dataset in another session as follows:

## Appendix B: fastai export

### Export a model

Exporting a fastai model as an encapsulated pickle file is also easy:

### Loading an exported model

Run the code block below if you’d like to load an existing fastai model and run inference on new data with it in colab:

<script type="application/vnd.jupyter.widget-state+json">
{"307700e692704d128c9000235a6f17c5": {"model_module": "@jupyter-widgets/controls", "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": "100%", "description_tooltip": null, "layout": "IPY_MODEL_411eb725c43c4adf9340a0a27ef061da", "max": 256198016, "min": 0, "orientation": "horizontal", "style": "IPY_MODEL_9e103a1d535a40fd8f417c8689884b8b", "value": 256198016}}, "411eb725c43c4adf9340a0a27ef061da": {"model_module": "@jupyter-widgets/base", "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}}, "451754fff86644b5912b33c58ac5981a": {"model_module": "@jupyter-widgets/base", "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}}, "49ec2b75718b473fa00541d7fb50259a": {"model_module": "@jupyter-widgets/base", "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}}, "53e8b0f53dbe492592b21c6c288ca914": {"model_module": "@jupyter-widgets/controls", "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_95c0356316274d999df93162d27da01d", "IPY_MODEL_e4499c59e6f8453699ba1921a82dc780"], "layout": "IPY_MODEL_49ec2b75718b473fa00541d7fb50259a"}}, "702a1184a1314468ba935e167a863cf8": {"model_module": "@jupyter-widgets/base", "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}}, "7281666eb2864344bdf7d8bf897cadaa": {"model_module": "@jupyter-widgets/base", "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}}, "8547c80a5f2645fea1d61c9a6d8cec16": {"model_module": "@jupyter-widgets/controls", "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": ""}}, "931041a5074542d192a1533f944ee789": {"model_module": "@jupyter-widgets/controls", "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": ""}}, "95c0356316274d999df93162d27da01d": {"model_module": "@jupyter-widgets/controls", "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": "100%", "description_tooltip": null, "layout": "IPY_MODEL_7281666eb2864344bdf7d8bf897cadaa", "max": 256198016, "min": 0, "orientation": "horizontal", "style": "IPY_MODEL_ed07f0250541454cbbd39c83b01aae6d", "value": 256198016}}, "9e103a1d535a40fd8f417c8689884b8b": {"model_module": "@jupyter-widgets/controls", "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": "initial"}}, "c0b89280a59d4f31aec03b9361fcffdd": {"model_module": "@jupyter-widgets/controls", "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_702a1184a1314468ba935e167a863cf8", "placeholder": "\\u200b", "style": "IPY_MODEL_8547c80a5f2645fea1d61c9a6d8cec16", "value": " 244M/244M [00:06&lt;00:00, 40.7MB/s]"}}, "c6c98e77502045719bc02b0a116e01a5": {"model_module": "@jupyter-widgets/base", "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}}, "dfe11b89f27a43ef9db67ccb96d3bad2": {"model_module": "@jupyter-widgets/controls", "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_307700e692704d128c9000235a6f17c5", "IPY_MODEL_c0b89280a59d4f31aec03b9361fcffdd"], "layout": "IPY_MODEL_c6c98e77502045719bc02b0a116e01a5"}}, "e4499c59e6f8453699ba1921a82dc780": {"model_module": "@jupyter-widgets/controls", "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_451754fff86644b5912b33c58ac5981a", "placeholder": "\\u200b", "style": "IPY_MODEL_931041a5074542d192a1533f944ee789", "value": " 244M/244M [00:06&lt;00:00, 42.2MB/s]"}}, "ed07f0250541454cbbd39c83b01aae6d": {"model_module": "@jupyter-widgets/controls", "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": "initial"}}}
</script>
