Jekyll2023-07-14T09:31:05-05:00https://manisnesan.github.io/chrestotes/feed.xmlChrestotesA Commonplace blog is to document my learning on whatever that interests me at the moment. Read more about the name Commonplace here https://en.wikipedia.org/wiki/Commonplace_bookTitle2023-04-14T00:00:00-05:002023-04-14T00:00:00-05:00https://manisnesan.github.io/chrestotes/2023/04/14/fashion-mnist<!--
#################################################
### THIS FILE WAS AUTOGENERATED! DO NOT EDIT! ###
#################################################
# file to edit: _notebooks/2023-04-14-fashion-mnist.ipynb
-->
<div class="container" id="notebook-container">
<div class="cell border-box-sizing code_cell rendered">
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Image-Classification-using-fastai-MidLevel-API">Image Classification using fastai MidLevel API<a class="anchor-link" href="#Image-Classification-using-fastai-MidLevel-API"> </a></h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<blockquote><p>In this blog post, we will explore a toy classification example using the Fashion MNIST dataset. We will discuss the limitations of the fastai DataBlock API and how learning about the Mid-level API can help overcome these limitations using Transforms, Pipeline, and Datasets. We will also cover the debugging steps involved in creating the Dataloaders for training image classifier & deploy the app using Gradio & HuggingFace spaces.</p>
</blockquote>
<p>See the complete app <a href="https://huggingface.co/spaces/msivanes/fashion-mnist-classifier/blob/main/app.py">Code</a> & <a href="https://huggingface.co/spaces/msivanes/fashion-mnist-classifier">Space</a></p>
<ul>
<li>toc: true </li>
<li>badges: true</li>
<li>comments: true</li>
<li>categories: [image-classification, machine-learning]</li>
<li>image: images/chart-preview.png</li>
</ul>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Setup">Setup<a class="anchor-link" href="#Setup"> </a></h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Context">Context<a class="anchor-link" href="#Context"> </a></h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>When working with the <a href="https://docs.fast.ai">fastai library</a>, we may encounter situations where the <a href="https://docs.fast.ai/tutorial.datablock.html">Data block API</a> is not flexible enough to handle our specific data processing needs. In such cases, we can use fastai's mid-level API, which provides a more comprehensive set of tools for processing data. The mid-level API includes a range of features such as Transforms, Pipeline, TfmdLists, Datasets, Callbacks, and General Optimizer. By using these, we can overcome the limitations of the Data block API and create more customized data processing pipelines to suit our specific use case.</p>
<p>To read more about Mid-Level API, please refer <a href="https://github.com/fastai/fastbook/blob/master/11_midlevel_data.ipynb">Chapter 11 - Data Munging with fastai's Mid-Level API</a> in fastbook.</p>
<p><img src="https://www.fast.ai/images/fastai_paper/layered.PNG" alt="fastai - a Layered API" /></p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>In this post, I wanted to share a toy classification example using Fashion MNIST dataset where the DataBlock API is not flexibile and how learning about Mid-level API using <code>Transforms</code>, <code>Pipeline</code> and <code>Datasets</code> helped to create the Dataloaders for training the model. We will use the model to create a image classifier predicting the target class given an black & white image of a fashion apparel using Gradio and HuggingFace spaces. We will also cover the debugging steps involved at the relevant step.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>The end to end workflow is as follows</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_svg output_subarea output_execute_result">
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 2.50.0 (0)
-->
<!-- Title: G Pages: 1 -->
<svg width="676pt" height="44pt" viewBox="0.00 0.00 675.85 44.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 40)">
<title>G</title>
<polygon fill="white" stroke="transparent" points="-4,4 -4,-40 671.85,-40 671.85,4 -4,4" />
<!-- Dataset -->
<g id="node1" class="node">
<title>Dataset</title>
<ellipse fill="none" stroke="black" cx="46.8" cy="-18" rx="46.59" ry="18" />
<text text-anchor="middle" x="46.8" y="-14.3" font-family="Times,serif" font-size="14.00">Dataset</text>
</g>
<!-- Dataloaders -->
<g id="node2" class="node">
<title>Dataloaders</title>
<ellipse fill="none" stroke="black" cx="196.54" cy="-18" rx="66.89" ry="18" />
<text text-anchor="middle" x="196.54" y="-14.3" font-family="Times,serif" font-size="14.00">Dataloaders</text>
</g>
<!-- Dataset->Dataloaders -->
<g id="edge1" class="edge">
<title>Dataset->Dataloaders</title>
<path fill="none" stroke="black" d="M93.73,-18C101.89,-18 110.58,-18 119.32,-18" />
<polygon fill="black" stroke="black" points="119.56,-21.5 129.56,-18 119.56,-14.5 119.56,-21.5" />
</g>
<!-- Train -->
<g id="node3" class="node">
<title>Train</title>
<ellipse fill="none" stroke="black" cx="334.58" cy="-18" rx="35.19" ry="18" />
<text text-anchor="middle" x="334.58" y="-14.3" font-family="Times,serif" font-size="14.00">Train</text>
</g>
<!-- Dataloaders->Train -->
<g id="edge2" class="edge">
<title>Dataloaders->Train</title>
<path fill="none" stroke="black" d="M263.56,-18C272.23,-18 280.93,-18 289.12,-18" />
<polygon fill="black" stroke="black" points="289.17,-21.5 299.17,-18 289.17,-14.5 289.17,-21.5" />
</g>
<!-- Predict_Item -->
<g id="node4" class="node">
<title>Predict_Item</title>
<ellipse fill="none" stroke="black" cx="475.87" cy="-18" rx="70.39" ry="18" />
<text text-anchor="middle" x="475.87" y="-14.3" font-family="Times,serif" font-size="14.00">Predict_Item</text>
</g>
<!-- Train->Predict_Item -->
<g id="edge3" class="edge">
<title>Train->Predict_Item</title>
<path fill="none" stroke="black" d="M370.01,-18C377.85,-18 386.5,-18 395.37,-18" />
<polygon fill="black" stroke="black" points="395.45,-21.5 405.45,-18 395.45,-14.5 395.45,-21.5" />
</g>
<!-- Deploy -->
<g id="node5" class="node">
<title>Deploy</title>
<ellipse fill="none" stroke="black" cx="624.96" cy="-18" rx="42.79" ry="18" />
<text text-anchor="middle" x="624.96" y="-14.3" font-family="Times,serif" font-size="14.00">Deploy</text>
</g>
<!-- Predict_Item->Deploy -->
<g id="edge4" class="edge">
<title>Predict_Item->Deploy</title>
<path fill="none" stroke="black" d="M546.11,-18C554.7,-18 563.37,-18 571.65,-18" />
<polygon fill="black" stroke="black" points="571.89,-21.5 581.89,-18 571.89,-14.5 571.89,-21.5" />
</g>
</g>
</svg>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Exploring-the-Dataset">Exploring the Dataset<a class="anchor-link" href="#Exploring-the-Dataset"> </a></h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<ul>
<li>Download and load dataset with the name <code>fashion_mnist</code> from <a href="https://huggingface.co/datasets/fashion_mnist">https://huggingface.co/datasets/fashion_mnist</a> using HuggingFace <strong>datasets</strong> library.</li>
</ul>
<blockquote><p>Fashion-MNIST is a dataset of Zalando's article images—consisting of a training set of 60,000 examples and a test set of 10,000 examples. Each example is a 28x28 grayscale image, associated with a label from 10 apparels such as t-shirt, ankle boot,</p>
</blockquote>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<ul>
<li>Explore the dataset using <code>load_dataset_builder</code> inspecting the dataset info such as description, features, splits etc</li>
</ul>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">name</span><span class="o">=</span><span class="s1">'fashion_mnist'</span>
<span class="n">ds_builder</span> <span class="o">=</span> <span class="n">load_dataset_builder</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="nb">print</span><span class="p">(</span><span class="n">ds_builder</span><span class="o">.</span><span class="n">info</span><span class="o">.</span><span class="n">description</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_subarea output_stream output_stdout output_text">
<pre>Fashion-MNIST is a dataset of Zalando's article images—consisting of a training set of
60,000 examples and a test set of 10,000 examples. Each example is a 28x28 grayscale image,
associated with a label from 10 classes. We intend Fashion-MNIST to serve as a direct drop-in
replacement for the original MNIST dataset for benchmarking machine learning algorithms.
It shares the same image size and structure of training and testing splits.
</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="nb">print</span><span class="p">(</span><span class="n">ds_builder</span><span class="o">.</span><span class="n">info</span><span class="o">.</span><span class="n">features</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_subarea output_stream output_stdout output_text">
<pre>{'image': Image(decode=True, id=None), 'label': ClassLabel(names=['T - shirt / top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot'], id=None)}
</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="nb">print</span><span class="p">(</span><span class="n">ds_builder</span><span class="o">.</span><span class="n">info</span><span class="o">.</span><span class="n">splits</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_subarea output_stream output_stdout output_text">
<pre>{'train': SplitInfo(name='train', num_bytes=31296655, num_examples=60000, shard_lengths=None, dataset_name=None), 'test': SplitInfo(name='test', num_bytes=5233818, num_examples=10000, shard_lengths=None, dataset_name=None)}
</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">ds_builder</span><span class="o">.</span><span class="n">info</span><span class="o">.</span><span class="n">features</span><span class="p">[</span><span class="s1">'label'</span><span class="p">]</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>ClassLabel(names=['T - shirt / top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot'], id=None)</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">ds_builder</span><span class="o">.</span><span class="n">info</span><span class="o">.</span><span class="n">features</span><span class="p">[</span><span class="s1">'label'</span><span class="p">]</span><span class="o">.</span><span class="n">int2str</span><span class="p">(</span><span class="mi">9</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>'Ankle boot'</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<ul>
<li>Load the dataset from the Hugging Face Hub specifying the name.</li>
</ul>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">dset</span> <span class="o">=</span> <span class="n">load_dataset</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>This is a <code>DatasetDict</code> containing a <code>train</code> and <a href="/chrestotes/images/copied_from_nb/test"><code>test</code></a> dataset dictionary within this object.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">dset</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>DatasetDict({
train: Dataset({
features: ['image', 'label'],
num_rows: 60000
})
test: Dataset({
features: ['image', 'label'],
num_rows: 10000
})
})</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<ul>
<li>We can inspect the individual item within train and test and the different labels.</li>
</ul>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">dset</span><span class="p">[</span><span class="s1">'train'</span><span class="p">][</span><span class="mi">0</span><span class="p">],</span> <span class="n">dset</span><span class="p">[</span><span class="s1">'test'</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>({'image': <PIL.PngImagePlugin.PngImageFile image mode=L size=28x28>,
'label': 9},
{'image': <PIL.PngImagePlugin.PngImageFile image mode=L size=28x28>,
'label': 9})</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Create-fastai-DataLoaders">Create fastai DataLoaders<a class="anchor-link" href="#Create-fastai-DataLoaders"> </a></h2><p>We eventually want to create <code>Datasets</code> object in fastai from HuggingFace <code>Dataset</code>. We will first attempt with the the high level <code>DataBlock</code> API and then transition to fastai <code>Datasets</code>.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<blockquote><p>DataBlock is a high level API in fastai allowing the user to define the standard steps to prepare the data for deep learning model.</p>
</blockquote>
<p>Steps involved to prepare the data</p>
<ul>
<li>Identify the types of inputs/targets for your data and define them as "Blocks".</li>
<li>Specify how to fetch and define any transformations that need to be applied to the inputs using the "get_x" function.</li>
<li>Specify how to fetch and define any transformations that need to be applied to the targets using the "get_y" function.</li>
<li>Split the data into training and validation sets using the "splitter" function.</li>
<li>Apply any additional transformations to the items using the "item_tfms" function.</li>
<li>Apply any additional transformations to the batches using the "batch_tfms" function.</li>
</ul>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Let's create training and test sets.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">train</span><span class="p">,</span> <span class="n">test</span> <span class="o">=</span> <span class="n">dset</span><span class="p">[</span><span class="s1">'train'</span><span class="p">],</span> <span class="n">dset</span><span class="p">[</span><span class="s1">'test'</span><span class="p">]</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Create an <code>Image</code> from argument using <code>PILImageBW.create</code> function</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">im</span> <span class="o">=</span> <span class="n">PILImageBW</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">train</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s1">'image'</span><span class="p">])</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Display the image using <code>show</code> method</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">im</span><span class="o">.</span><span class="n">show</span><span class="p">()</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre><AxesSubplot:></pre>
</div>
</div>
<div class="output_area">
<div class="output_png output_subarea ">
<img src="data:image/png;base64,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" />
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Let's examine the type of the features (ie Image) and label</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="nb">type</span><span class="p">(</span><span class="n">train</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s1">'image'</span><span class="p">])</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>PIL.PngImagePlugin.PngImageFile</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Let's examine the first 3 training samples</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">train</span><span class="p">[:</span><span class="mi">3</span><span class="p">]</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>{'image': [<PIL.PngImagePlugin.PngImageFile image mode=L size=28x28>,
<PIL.PngImagePlugin.PngImageFile image mode=L size=28x28>,
<PIL.PngImagePlugin.PngImageFile image mode=L size=28x28>],
'label': [9, 0, 0]}</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>The type of <code>label</code> is an <code>int</code> but since fastai also performs <code>Categorize</code> transform we can create a separate <code>target</code> which contains the original apparel name. This can be achieved using <code>ClassLabel.int2str</code> method.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">classLabel</span> <span class="o">=</span> <span class="n">ClassLabel</span><span class="p">(</span><span class="n">names</span><span class="o">=</span><span class="p">[</span><span class="s1">'T - shirt / top'</span><span class="p">,</span> <span class="s1">'Trouser'</span><span class="p">,</span> <span class="s1">'Pullover'</span><span class="p">,</span> <span class="s1">'Dress'</span><span class="p">,</span> <span class="s1">'Coat'</span><span class="p">,</span> <span class="s1">'Sandal'</span><span class="p">,</span> <span class="s1">'Shirt'</span><span class="p">,</span> <span class="s1">'Sneaker'</span><span class="p">,</span> <span class="s1">'Bag'</span><span class="p">,</span> <span class="s1">'Ankle boot'</span><span class="p">],</span> <span class="nb">id</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">add_target</span><span class="p">(</span><span class="n">x</span><span class="p">:</span><span class="nb">dict</span><span class="p">):</span>
<span class="n">x</span><span class="p">[</span><span class="s1">'target'</span><span class="p">]</span> <span class="o">=</span> <span class="n">classLabel</span><span class="o">.</span><span class="n">int2str</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="s1">'label'</span><span class="p">])</span>
<span class="k">return</span> <span class="n">x</span>
<span class="n">train</span> <span class="o">=</span> <span class="n">train</span><span class="o">.</span><span class="n">map</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">add_target</span><span class="p">(</span><span class="n">x</span><span class="p">))</span>
<span class="n">valid</span> <span class="o">=</span> <span class="n">test</span><span class="o">.</span><span class="n">map</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">add_target</span><span class="p">(</span><span class="n">x</span><span class="p">))</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">train</span><span class="p">[:</span><span class="mi">3</span><span class="p">],</span> <span class="n">valid</span><span class="p">[:</span><span class="mi">3</span><span class="p">]</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>({'image': [<PIL.PngImagePlugin.PngImageFile image mode=L size=28x28>,
<PIL.PngImagePlugin.PngImageFile image mode=L size=28x28>,
<PIL.PngImagePlugin.PngImageFile image mode=L size=28x28>],
'label': [9, 0, 0],
'target': ['Ankle boot', 'T - shirt / top', 'T - shirt / top']},
{'image': [<PIL.PngImagePlugin.PngImageFile image mode=L size=28x28>,
<PIL.PngImagePlugin.PngImageFile image mode=L size=28x28>,
<PIL.PngImagePlugin.PngImageFile image mode=L size=28x28>],
'label': [9, 2, 1],
'target': ['Ankle boot', 'Pullover', 'Trouser']})</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Now we can concatenate training and validation datasets into a single set of items which can be passed to fastai <code>Datasets</code> with index from 60000 to 70000 set aside as validation set.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">concat_dsets</span> <span class="o">=</span> <span class="n">concatenate_datasets</span><span class="p">([</span><span class="n">train</span><span class="p">,</span> <span class="n">valid</span><span class="p">])</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">concat_dsets</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>Dataset({
features: ['image', 'label', 'target'],
num_rows: 70000
})</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Attempting-to-use-DataBlock">Attempting to use DataBlock<a class="anchor-link" href="#Attempting-to-use-DataBlock"> </a></h3>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Let's first create a <code>DataBlock</code> and then learn how to create <code>Datasets</code>. In order to inform fastai on how to turn the data into <code>DataLoaders</code> object, 4 key pieces of info are needed.</p>
<ol>
<li>the kind of data used for inputs and the target </li>
<li>Getters for the list of items </li>
<li>Labeling the items </li>
<li>Validation set creation</li>
</ol>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p><div class="flash flash-success">
<svg class="octicon octicon-checklist" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M16 8.5l-6 6-3-3L8.5 10l1.5 1.5L14.5 7 16 8.5zM5.7 12.2l.8.8H2c-.55 0-1-.45-1-1V3c0-.55.45-1 1-1h7c.55 0 1 .45 1 1v6.5l-.8-.8c-.39-.39-1.03-.39-1.42 0L5.7 10.8a.996.996 0 000 1.41v-.01zM4 4h5V3H4v1zm0 2h5V5H4v1zm0 2h3V7H4v1zM3 9H2v1h1V9zm0-2H2v1h1V7zm0-2H2v1h1V5zm0-2H2v1h1V3z"></path></svg>
<strong>Tip: </strong>It’s best to create <code>DataBlock</code> in an iterative manner and running <code>datablock.summary</code> to understand the pieces that fastai adds behind the scenes.
</div></p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="k">def</span> <span class="nf">get_image_attr</span><span class="p">(</span><span class="n">x</span><span class="p">):</span> <span class="k">return</span> <span class="n">x</span><span class="p">[</span><span class="s1">'image'</span><span class="p">]</span>
<span class="k">def</span> <span class="nf">get_target_attr</span><span class="p">(</span><span class="n">x</span><span class="p">):</span> <span class="k">return</span> <span class="n">x</span><span class="p">[</span><span class="s1">'target'</span><span class="p">]</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">Image</span><span class="o">.</span><span class="n">fromarray</span><span class="p">(</span><span class="n">array</span><span class="p">(</span><span class="n">train</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s1">'image'</span><span class="p">]))</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_png output_subarea output_execute_result">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAAAAABXZoBIAAACBUlEQVR4nLXSz0tUURQH8O+597373rx545g6NmNJY6TlJgozEsKFZGCrkDBoVdGmdf9BiwJ3bVr1PwhBUbQfJQcKjWZRTsjo0KDpDPV+eN+997WK0Z2bvtsPfM+Bc4D/HwJycwBZAEAE6zAyfe5RFMQfFYiRAj+CXM/c2HK82VetVMM34RGUmCxz9v7yYnW9dnWyskyHR6azi72Jwep3ScVk9c7LLhKQrpRBSiI2n76puZFT3doUwH4pcmw/zpjrU2zw3dFt4XEWdvbKhpinzTBYt5bDH4qlLYO8cbKBWHOudDHluFtiLrLD0kmM2//6q9VFS+JLLDxv9GzMPV9v3XuzYgHEGSUGCngbRCLd4W6CxPCLHTDwVMkDA0y/qEa/lFFBoF2EEME8CAD6hsZK8+djlmSatuiXXsWfNh27NU6Yelro1bytPElRbaGaO1FGPfc7zPg9HvHlIaVD8AjID9y/+bgZ/6iP9ks7J/QZevh8w/cd2PlGs8CKt92R7MQEk0yA7GtWq9ETN3zRs7fpR7FaWi/3yXaipW1IjFnbaSM70N7dsRzbzbHd8aCx7+wmKskUO5esz0sPmvXYF67gBzoNfxptxb5stxM10iLg1pOTO23NhcUptW1hE6gFYYprC8QMMPNsMM+4pamVbps/HGkSsg+1Cv4d+0Jh//Sm3DjGix4rfwFoJNh2/0cDFgAAAABJRU5ErkJggg==" />
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="k">def</span> <span class="nf">image2tensor</span><span class="p">(</span><span class="n">img</span><span class="p">):</span>
<span class="s2">"Transform image to byte tensor in `c*h*w` dim order."</span>
<span class="n">res</span> <span class="o">=</span> <span class="n">tensor</span><span class="p">(</span><span class="n">img</span><span class="p">)</span>
<span class="k">if</span> <span class="n">res</span><span class="o">.</span><span class="n">dim</span><span class="p">()</span><span class="o">==</span><span class="mi">2</span><span class="p">:</span> <span class="n">res</span> <span class="o">=</span> <span class="n">res</span><span class="o">.</span><span class="n">unsqueeze</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="k">return</span> <span class="n">res</span><span class="o">.</span><span class="n">permute</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="nb">type</span><span class="p">(</span><span class="n">image2tensor</span><span class="p">(</span><span class="n">train</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s1">'image'</span><span class="p">]))</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>torch.Tensor</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>We will discuss <code>image2tensor</code> function when we discuss <code>Attempting with Datasets</code></p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>This shows how to specify the indices that need to be part of validation set. Indices 6, 7, 8 & 9 are in validation and rest are in training set.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">IndexSplitter</span><span class="p">(</span><span class="n">valid_idx</span><span class="o">=</span><span class="n">L</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">6</span><span class="p">,</span> <span class="mi">10</span><span class="p">)))(</span><span class="n">concat_dsets</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>((#69996) [0,1,2,3,4,5,10,11,12,13...], (#4) [6,7,8,9])</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>DataBlock definition is as follows</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">dblock</span> <span class="o">=</span> <span class="n">DataBlock</span><span class="p">(</span><span class="n">blocks</span><span class="o">=</span><span class="p">(</span><span class="n">ImageBlock</span><span class="p">(</span><span class="bp">cls</span><span class="o">=</span><span class="n">PILImageBW</span><span class="p">),</span> <span class="n">CategoryBlock</span><span class="p">),</span>
<span class="n">get_x</span><span class="o">=</span><span class="n">Pipeline</span><span class="p">([</span><span class="n">get_image_attr</span><span class="p">,</span> <span class="n">image2tensor</span><span class="p">]),</span>
<span class="n">get_y</span><span class="o">=</span><span class="n">get_target_attr</span><span class="p">,</span>
<span class="n">splitter</span><span class="o">=</span><span class="n">IndexSplitter</span><span class="p">(</span><span class="n">valid_idx</span><span class="o">=</span><span class="n">L</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">60000</span><span class="p">,</span> <span class="mi">70000</span><span class="p">))),</span>
<span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Run the <code>DataBlock.summary</code> to understand how fastai set up the data pipeline and perform the necessary transforms.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="c1">#Output cleared</span>
<span class="c1">#dblock.summary(concat_dsets)</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Traceback while running <code>dblock.summary(concat_dsets)</code></p>
<pre><code>Setting-up type transforms pipelines
Collecting items from Dataset({
features: ['image', 'label', 'target'],
num_rows: 70000
})
Found 70000 items
2 datasets of sizes 60000,10000
Setting up Pipeline: get_image_attr -> image2tensor -> PILBase.create
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
~/miniconda3/envs/fastai/lib/python3.9/site-packages/PIL/Image.py in fromarray(obj, mode)
2812 try:
-> 2813 mode, rawmode = _fromarray_typemap[typekey]
2814 except KeyError as e:
KeyError: ((1, 1, 28), '|u1')</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Essentially the data pipeline is as follows</p>
<ul>
<li>Get the image attribute from the item, Convert the image to tensor. But fastai also adds the <code>PILBase.create</code> since we specified ImageBlock as our independent variable. This caused an issue <code>KeyError: ((1, 1, 28), '|u1')</code> due to <code>Image.fromarray</code> function used in <code>PILBase.create</code>. From <a href="https://stackoverflow.com/questions/57621092/keyerror-1-1-1280-u1-while-using-pils-image-fromarray-pil">https://stackoverflow.com/questions/57621092/keyerror-1-1-1280-u1-while-using-pils-image-fromarray-pil</a><blockquote><p>Pillow's fromarray function can only do a MxNx3 array (RGB image), or an MxN array (grayscale).</p>
</blockquote>
</li>
</ul>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<ul>
<li>Internally fastai calls <code>load_image</code> with the item during the data pipeline creation as part of <code>PILBase.create</code> which fastai adds by default if we specify <code>ImageBlock</code> as part of blocks section in the DataBlock.</li>
</ul>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="k">def</span> <span class="nf">load_image</span><span class="p">(</span><span class="n">fn</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="s2">"Open and load a `PIL.Image` and convert to `mode`"</span>
<span class="n">im</span> <span class="o">=</span> <span class="n">Image</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">fn</span><span class="p">)</span>
<span class="n">im</span><span class="o">.</span><span class="n">load</span><span class="p">()</span>
<span class="n">im</span> <span class="o">=</span> <span class="n">im</span><span class="o">.</span><span class="n">_new</span><span class="p">(</span><span class="n">im</span><span class="o">.</span><span class="n">im</span><span class="p">)</span>
<span class="k">return</span> <span class="n">im</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="n">mode</span><span class="p">)</span> <span class="k">if</span> <span class="n">mode</span> <span class="k">else</span> <span class="n">im</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p><code>load_image</code> requires a filename but dataset already is in <code>PIL.PngImagePlugin.PngImageFile</code></p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p><code>Image.open(train[0]['image'])</code> will lead to the following error from pillow library.</p>
<pre><code>---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-18-ed0e9de325b8> in <module>
----> 1 Image.open(train[0]['image'])
1 frames
/usr/local/lib/python3.8/dist-packages/PIL/Image.py in __getattr__(self, name)
544 )
545 return self._category
--> 546 raise AttributeError(name)
547
548 @property</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Attempt-with-MidLevel-API-Datasets">Attempt with MidLevel API Datasets<a class="anchor-link" href="#Attempt-with-MidLevel-API-Datasets"> </a></h3>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>We want to convert the Image of size [28 ,28] into [1, 28, 28] as our end goal and decided to perform the item transforms using Mid Level API instead. - <code>Datasets</code> in MidLevel API provides more flexibility and full control over the individual item transforms performed.</p>
<blockquote><p>Datasets is part of MidLevel API allowing the user to customize the steps involved in data processing that are
not possible with DataBlockAPI</p>
</blockquote>
<p>Datasets need the following pieces of information</p>
<ul>
<li>raw items</li>
<li>the list of transforms that builds our inputs from the raw items</li>
<li>the list of transforms that builds our targets from the raw items</li>
<li>the split for training and validation</li>
</ul>
<p>For a deeper dive, refer loading the data with mid level api section on <a href="https://docs.fast.ai/tutorial.imagenette.html#loading-the-data-with-the-mid-level-api">Training Imagenette tutorial</a> and Wayde Gilliam <a href="https://ohmeow.com/posts/2020/04/11/finding-datablock-nirvana-part-1.html">blog post</a>
Let's iterate on the individual pieces of info.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Let's investigate the item transforms that we need for the Image. PyTorch Model expects the items to of type <code>torch.Tensor</code>. So I used <code>ToTensor</code> but it did not convert to tensors as I expected for the Image of type <code>PIL.PngImagePlugin.PngImageFile</code>. So I created <code>img2tensor</code> instead.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="nb">type</span><span class="p">(</span><span class="n">train</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s1">'image'</span><span class="p">])</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>PIL.PngImagePlugin.PngImageFile</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="nb">type</span><span class="p">(</span><span class="n">ToTensor</span><span class="p">()(</span><span class="n">train</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s1">'image'</span><span class="p">]))</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>PIL.PngImagePlugin.PngImageFile</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Referred what fastai does underneath using the source code. This is the function that takes the image and converts the image to a byte tensor of shape <code>c*h*w</code> ie channel x height x width</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="k">def</span> <span class="nf">image2tensor</span><span class="p">(</span><span class="n">img</span><span class="p">):</span>
<span class="s2">"Transform image to byte tensor in `c*h*w` dim order."</span>
<span class="n">res</span> <span class="o">=</span> <span class="n">tensor</span><span class="p">(</span><span class="n">img</span><span class="p">)</span>
<span class="k">if</span> <span class="n">res</span><span class="o">.</span><span class="n">dim</span><span class="p">()</span><span class="o">==</span><span class="mi">2</span><span class="p">:</span> <span class="n">res</span> <span class="o">=</span> <span class="n">res</span><span class="o">.</span><span class="n">unsqueeze</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="k">return</span> <span class="n">res</span><span class="o">.</span><span class="n">permute</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="nb">type</span><span class="p">(</span><span class="n">image2tensor</span><span class="p">(</span><span class="n">train</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s1">'image'</span><span class="p">]))</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>torch.Tensor</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>I created my own version of it in <code>img2tensor</code></p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="k">def</span> <span class="nf">img2tensor</span><span class="p">(</span><span class="n">im</span><span class="p">:</span> <span class="n">Image</span><span class="o">.</span><span class="n">Image</span><span class="p">):</span>
<span class="k">return</span> <span class="n">TensorImageBW</span><span class="p">(</span><span class="n">array</span><span class="p">(</span><span class="n">im</span><span class="p">))</span><span class="o">.</span><span class="n">unsqueeze</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">img2tensor</span><span class="p">(</span><span class="n">train</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s1">'image'</span><span class="p">])</span><span class="o">.</span><span class="n">shape</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>torch.Size([1, 28, 28])</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">tensor</span><span class="p">(</span><span class="n">train</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s1">'image'</span><span class="p">])</span><span class="o">.</span><span class="n">unsqueeze</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">permute</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">shape</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>torch.Size([1, 28, 28])</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">TensorImageBW</span><span class="p">(</span><span class="n">array</span><span class="p">(</span><span class="n">im</span><span class="p">))</span><span class="o">.</span><span class="n">unsqueeze</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">shape</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>torch.Size([1, 28, 28])</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">test_eq</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">28</span><span class="p">,</span> <span class="mi">28</span><span class="p">],</span> <span class="n">img2tensor</span><span class="p">(</span><span class="n">train</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s1">'image'</span><span class="p">])</span><span class="o">.</span><span class="n">shape</span><span class="p">)</span>
<span class="n">test_eq</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">28</span><span class="p">,</span> <span class="mi">28</span><span class="p">],</span> <span class="n">image2tensor</span><span class="p">(</span><span class="n">train</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s1">'image'</span><span class="p">])</span><span class="o">.</span><span class="n">shape</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>As you can see both image2tensor and img2tensor behaves the same way.Now the input item is ready. Let's look at the target.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">concat_dsets</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>Dataset({
features: ['image', 'label', 'target'],
num_rows: 70000
})</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>fasti internally converts the label and encodes them into numbers by creating a vocabulary of labels using <code>Categorize</code> transform.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">Categorize</span><span class="p">(</span><span class="n">vocab</span><span class="o">=</span><span class="n">ds_builder</span><span class="o">.</span><span class="n">info</span><span class="o">.</span><span class="n">features</span><span class="p">[</span><span class="s1">'label'</span><span class="p">]</span><span class="o">.</span><span class="n">names</span><span class="p">,</span> <span class="n">sort</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>Categorize -- {'vocab': ['T - shirt / top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot'], 'sort': False, 'add_na': False}:
encodes: (Tabular,object) -> encodes
(object,object) -> encodes
decodes: (Tabular,object) -> decodes
(object,object) -> decodes</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Create the Datasets definition as follows</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">splits</span> <span class="o">=</span> <span class="n">IndexSplitter</span><span class="p">(</span><span class="n">valid_idx</span><span class="o">=</span><span class="n">L</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">60000</span><span class="p">,</span> <span class="mi">70000</span><span class="p">)))(</span><span class="n">concat_dsets</span><span class="p">)</span>
<span class="n">dsets</span> <span class="o">=</span> <span class="n">Datasets</span><span class="p">(</span><span class="n">concat_dsets</span><span class="p">,</span>
<span class="p">[[</span><span class="n">get_image_attr</span><span class="p">],</span>
<span class="p">[</span><span class="n">get_target_attr</span><span class="p">,</span> <span class="n">Categorize</span><span class="p">]],</span>
<span class="n">splits</span><span class="o">=</span><span class="n">splits</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Define the item transformations and batch transformations</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">item_tfms</span> <span class="o">=</span> <span class="p">[</span><span class="n">img2tensor</span><span class="p">]</span> <span class="c1"># convert PILImage to tensors</span>
<span class="n">batch_tfms</span> <span class="o">=</span> <span class="p">[</span><span class="n">IntToFloatTensor</span><span class="p">]</span> <span class="c1"># convert the int tensors from images to floats, and divide every pixel by 255</span>
<span class="n">dls</span> <span class="o">=</span> <span class="n">dsets</span><span class="o">.</span><span class="n">dataloaders</span><span class="p">(</span><span class="n">after_item</span><span class="o">=</span><span class="n">item_tfms</span><span class="p">,</span> <span class="n">after_batch</span><span class="o">=</span><span class="n">batch_tfms</span><span class="p">,</span> <span class="n">bs</span><span class="o">=</span><span class="mi">64</span><span class="p">,</span> <span class="n">num_workers</span><span class="o">=</span><span class="mi">8</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Visualize the items in a batch</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">dls</span><span class="o">.</span><span class="n">show_batch</span><span class="p">()</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_png output_subarea ">
<img src="data:image/png;base64,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RmW/k9sYDiQECAAAapgAAACQISYAAABkiAkAAAAZIgSIjtQdAlRdNoavvvrqpPboo48mNdd5r0+fPknNBaokH5TaY489kpoLeLnHTpgwIanNnz8/qY0bN84ej9u3C0+5QNbpp5+e1I477ji7n0adGZ7qAl02jt///vcnNRcMdEtLu6Chq0lSr169kpoLFh5//PFJzZ1Xzq677prUXnzxRbttWTiwkTtu10XwrW99a1I777zzklrZz6ctHTZFCBAAAGzDBAAAgAwxAQAAIENMAAAAyBATAAAAMlQt5ghgu6644oqk5tZCnzJlSlIbPHhwUnNtSHfffXe7b/d4l2x27Xx79+6d1IYPH16pNmjQIHs8K1eurLTtCy+8kNSuvPLKpOZaxLp2xR20jnpWXJvdRYsWJbW99947qbnX06Xuy1Luru7eIePG7J577pnUVqxYkdTcO1TKuONx3497h4s7Jx966KGk5t4F0Ma0f6twBwAAgAwxAQAAIENMAAAAyBATAAAAMkQIEGglF0y66667ktqYMWOSmgv4uMCea2vrwkaSD1+5tqyOCxa6Fr3Lli1Lai7sJ/kwngvyuX3vt99+Se22225Laq985SuTWmeGp3oq9zq5QGrV19ONYxekk/zrVzVY6Pbtxuf48eMr7aOMO1fdz8d9L+543DndmqBiW3HGAACQISYAAABkiAkAAAAZYgIAAECGCAECreRCaZs2bUpqW7duTWouQOi6mLk1xsu40J17vFvf3AWgXDc499iq66VL/hhdp7WqQbAZM2YktUMOOaTy8cBbsmRJpe1cEM8FA12grWzcuNe+X79+Sc2NTxd6dc/n9u2Ou2xbd067sV01BOhqo0aNssfTEbgDAABAhpgAAACQISYAAABkiAkAAAAZavoQoOs01RHLgnbWfn70ox8ltSOOOCKp/c3f/E2l56satCrTWd93M7n77ruT2sCBA5Pa2rVrk1r//v2TWtUQUdkyqlVfIxfIckurumMs60LoVA0wuq5qGzZsSGoucEYIsGNMmzat0nZVl/l1Y9O97pLUp0+fSvtx42v58uWVjsftu+x4HPf9uLBg1ee8//77k9qb3/zmysfTVtwBAAAgQ0wAAADIEBMAAAAyxAQAAIAMNX0IsBkCf4sXL05qX//61+22f/rTn5KaC7jMmzev0r7bukRq7oE/xwWlXABt0aJF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Nz+3pLMLcqL9LVy40NarXnfda+8ChPPnz09qrQl6usCgG9vNjDsAAABkiAkAAAAZYgIAAECGmAAAAJChHhkC3H///ZNaWTc9F9Crutxk1a5/7vnKli51AZc999yz0vEQ+KvGBf5aE6B09Ve/+tWVao5bdtgFkBYsWGAff9999yW1I488MqlNnTq10vF0BLfM7xe/+MWk5r5Hd064boWt8b73vS+puesG2p8bC5IPs1bt4njPPfckNdep0i0LX9YJ0HUsLFtWvllxBwAAgAwxAQAAIENMAAAAyBATAAAAMsQEAACADPXIdwEMHjw4qZW9C2DcuHFJraxtcCOXTq7aCti1apWkVatWJTW3lrrj9tOalqk568p3UEyYMKHSdvvss4+tv+IVr2jPw+kQv//977v6ENBNuNbMkr/29erVK6m59tWPPvpoUnPv9nHXw7LrfZ8+fZKae2dAM+MOAAAAGWICAABAhpgAAACQISYAAABkqKlCgFXXcb/wwguTmlsbWpIeeeSRpPbCCy8kNRdGaUuL0t128z96F+j6/Oc/X+k5aQUMoLsrCwGuW7cuqbk26C5o7VoBu+dz18iya/b06dNtvSfhDgAAABliAgAAQIaYAAAAkCEmAAAAZChcoKKF7X6xJ1i+fHlSu/3225PaokWLktrGjRuT2jnnnJPURowYkdTKuk9VXW+6NevXd6HucEA9fgyjQ3WHMSz1oHF866232vpFF12U1FwIcK+99kpqxx13XFK77777ktrSpUuT2u67726PZ+LEiUnthz/8od22CdhxzB0AAAAyxAQAAIAMMQEAACBDTAAAAMjQjkKAAACgB+IOAAAAGWICAABAhpgAAACQISYAAABkiAkAAAAZYgIAAECG/h9Z2Z3FXpbmDAAAAABJRU5ErkJggg==" />
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Verify the items and their shapes in a single batch</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">xb</span><span class="p">,</span> <span class="n">yb</span> <span class="o">=</span> <span class="n">dls</span><span class="o">.</span><span class="n">one_batch</span><span class="p">()</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">xb</span><span class="o">.</span><span class="n">shape</span><span class="p">,</span> <span class="n">yb</span><span class="o">.</span><span class="n">shape</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>(torch.Size([64, 1, 28, 28]), torch.Size([64]))</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">dls</span><span class="o">.</span><span class="n">c</span> <span class="c1"># 10 classes as targets</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>10</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">dls</span><span class="o">.</span><span class="n">vocab</span> <span class="c1"># targets vocabulary</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>['Ankle boot', 'Bag', 'Coat', 'Dress', 'Pullover', 'Sandal', 'Shirt', 'Sneaker', 'T - shirt / top', 'Trouser']</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Train-the-Model">Train the Model<a class="anchor-link" href="#Train-the-Model"> </a></h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>For training a image classification model, resnet architecture (a form on convolution neural network) is used as our backbone and fully connected (fc) linear layer as our head. In order for the linear layer to predict the outputs as one of the classes, pass the number of classes in order to configure the final layer. For overview review <a href="https://www.indusmic.com/post/transfer-learning-and-fine-tuning-of-neural-networks">this resource</a> about <a href="https://www.ruder.io/transfer-learning/">transfer learning</a> and fine tuning.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Review the model layers</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="c1">#gpu required</span>
<span class="n">model</span> <span class="o">=</span> <span class="n">resnet34</span><span class="p">(</span><span class="n">num_classes</span><span class="o">=</span><span class="n">dls</span><span class="o">.</span><span class="n">c</span><span class="p">)</span><span class="o">.</span><span class="n">cuda</span><span class="p">()</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="c1">#gpu required</span>
<span class="n">model</span><span class="o">.</span><span class="n">avgpool</span><span class="p">,</span> <span class="n">model</span><span class="o">.</span><span class="n">fc</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="c1"># Uncomment this line to validate if the model accepts single batch as input</span>
<span class="c1"># model(xb)</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>We can access the convolutional layers as attributes of the model.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Input to the convolutional layer is set as 3 channel (RGB) image but the images used as inputs are single channel images. Let's update the input channel to single channel.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="c1">#gpu required</span>
<span class="n">model</span><span class="o">.</span><span class="n">conv1</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="c1">#gpu required</span>
<span class="n">model</span><span class="o">.</span><span class="n">conv1</span> <span class="o">=</span> <span class="n">nn</span><span class="o">.</span><span class="n">Conv2d</span><span class="p">(</span><span class="n">in_channels</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">out_channels</span><span class="o">=</span><span class="mi">64</span><span class="p">,</span> <span class="n">kernel_size</span><span class="o">=</span><span class="p">(</span><span class="mi">7</span><span class="p">,</span> <span class="mi">7</span><span class="p">),</span> <span class="n">stride</span><span class="o">=</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="n">padding</span><span class="o">=</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span> <span class="n">bias</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="c1">#gpu required</span>
<span class="n">model</span><span class="o">.</span><span class="n">cuda</span><span class="p">();</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="c1">#gpu required</span>
<span class="n">model</span><span class="p">(</span><span class="n">xb</span><span class="p">);</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Learner">Learner<a class="anchor-link" href="#Learner"> </a></h3>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p><code>Learner</code> is a class that combines the ingredients such as data, model and metrics used to train a model.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">learn</span> <span class="o">=</span> <span class="n">Learner</span><span class="p">(</span><span class="n">dls</span><span class="p">,</span> <span class="n">model</span><span class="p">,</span> <span class="n">metrics</span><span class="o">=</span><span class="n">accuracy</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p><code>pretrained=False</code> type setting is used since the fashnion mnist is not similar dataset as Imagenet so keeping all the layers are trainable. If in case <code>pretrained=True</code>, we may want to freeze the layers except the head and do a bit of fine tuning the head first followed by unfreeze & then train all the layers.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Review the learner summary to know about the input shape, output shape, different layers involved, parameters, trainable, Optimizer used and loss function used.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">learn</span><span class="o">.</span><span class="n">summary</span><span class="p">()</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_html rendered_html output_subarea ">
<style>
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
progress:not([value]), progress:not([value])::-webkit-progress-bar {
background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
</style>
</div>
</div>
<div class="output_area">
<div class="output_html rendered_html output_subarea ">
</div>
</div>
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>ResNet (Input shape: 64 x 1 x 28 x 28)
============================================================================
Layer (type) Output Shape Param # Trainable
============================================================================
64 x 64 x 14 x 14
Conv2d 3136 True
BatchNorm2d 128 True
ReLU
____________________________________________________________________________
64 x 64 x 7 x 7
MaxPool2d
Conv2d 36864 True
BatchNorm2d 128 True
ReLU
Conv2d 36864 True
BatchNorm2d 128 True
Conv2d 36864 True
BatchNorm2d 128 True
ReLU
Conv2d 36864 True
BatchNorm2d 128 True
Conv2d 36864 True
BatchNorm2d 128 True
ReLU
Conv2d 36864 True
BatchNorm2d 128 True
____________________________________________________________________________
64 x 128 x 4 x 4
Conv2d 73728 True
BatchNorm2d 256 True
ReLU
Conv2d 147456 True
BatchNorm2d 256 True
Conv2d 8192 True
BatchNorm2d 256 True
Conv2d 147456 True
BatchNorm2d 256 True
ReLU
Conv2d 147456 True
BatchNorm2d 256 True
Conv2d 147456 True
BatchNorm2d 256 True
ReLU
Conv2d 147456 True
BatchNorm2d 256 True
Conv2d 147456 True
BatchNorm2d 256 True
ReLU
Conv2d 147456 True
BatchNorm2d 256 True
____________________________________________________________________________
64 x 256 x 2 x 2
Conv2d 294912 True
BatchNorm2d 512 True
ReLU
Conv2d 589824 True
BatchNorm2d 512 True
Conv2d 32768 True
BatchNorm2d 512 True
Conv2d 589824 True
BatchNorm2d 512 True
ReLU
Conv2d 589824 True
BatchNorm2d 512 True
Conv2d 589824 True
BatchNorm2d 512 True
ReLU
Conv2d 589824 True
BatchNorm2d 512 True
Conv2d 589824 True
BatchNorm2d 512 True
ReLU
Conv2d 589824 True
BatchNorm2d 512 True
Conv2d 589824 True
BatchNorm2d 512 True
ReLU
Conv2d 589824 True
BatchNorm2d 512 True
Conv2d 589824 True
BatchNorm2d 512 True
ReLU
Conv2d 589824 True
BatchNorm2d 512 True
____________________________________________________________________________
64 x 512 x 1 x 1
Conv2d 1179648 True
BatchNorm2d 1024 True
ReLU
Conv2d 2359296 True
BatchNorm2d 1024 True
Conv2d 131072 True
BatchNorm2d 1024 True
Conv2d 2359296 True
BatchNorm2d 1024 True
ReLU
Conv2d 2359296 True
BatchNorm2d 1024 True
Conv2d 2359296 True
BatchNorm2d 1024 True
ReLU
Conv2d 2359296 True
BatchNorm2d 1024 True
AdaptiveAvgPool2d
____________________________________________________________________________
64 x 10
Linear 5130 True
____________________________________________________________________________
Total params: 21,283,530
Total trainable params: 21,283,530
Total non-trainable params: 0
Optimizer used: <function Adam>
Loss function: FlattenedLoss of CrossEntropyLoss()
Callbacks:
- TrainEvalCallback
- CastToTensor
- Recorder
- ProgressCallback</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Learning rate, a hyperparameter used for training can be determined using learning rate finder function in fastai</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">learn</span><span class="o">.</span><span class="n">lr_find</span><span class="p">()</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_html rendered_html output_subarea ">
<style>
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
progress:not([value]), progress:not([value])::-webkit-progress-bar {
background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
</style>
</div>
</div>
<div class="output_area">
<div class="output_html rendered_html output_subarea ">
</div>
</div>
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>SuggestedLRs(valley=0.0004786300996784121)</pre>
</div>
</div>
<div class="output_area">
<div class="output_png output_subarea ">
<img src="data:image/png;base64,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" />
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Train the deep learning model with 6 epochs and with the learning rate obtained from previous step</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">learn</span><span class="o">.</span><span class="n">fit_one_cycle</span><span class="p">(</span><span class="mi">6</span><span class="p">,</span> <span class="mf">5e-3</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_html rendered_html output_subarea ">
<style>
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
progress:not([value]), progress:not([value])::-webkit-progress-bar {
background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
</style>
</div>
</div>
<div class="output_area">
<div class="output_html rendered_html output_subarea ">
<table border="1" class="dataframe">
<thead>
<tr style="text-align: left;">
<th>epoch</th>
<th>train_loss</th>
<th>valid_loss</th>
<th>accuracy</th>
<th>time</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td>0.350417</td>
<td>0.380862</td>
<td>0.860200</td>
<td>01:17</td>
</tr>
<tr>
<td>1</td>
<td>0.350359</td>
<td>0.350519</td>
<td>0.867500</td>
<td>01:18</td>
</tr>
<tr>
<td>2</td>
<td>0.266588</td>
<td>0.297127</td>
<td>0.889900</td>
<td>01:19</td>
</tr>
<tr>
<td>3</td>
<td>0.215826</td>
<td>0.248561</td>
<td>0.909700</td>
<td>01:16</td>
</tr>
<tr>
<td>4</td>
<td>0.173092</td>
<td>0.230798</td>
<td>0.918000</td>
<td>01:18</td>
</tr>
<tr>
<td>5</td>
<td>0.139866</td>
<td>0.226217</td>
<td>0.922900</td>
<td>01:17</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Model is trained with an accuracy of <strong>92.3%</strong>.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Exporting-the-trained-model">Exporting the trained model<a class="anchor-link" href="#Exporting-the-trained-model"> </a></h3>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p><div class="flash flash-success">
<svg class="octicon octicon-checklist octicon octicon-checklist" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M16 8.5l-6 6-3-3L8.5 10l1.5 1.5L14.5 7 16 8.5zM5.7 12.2l.8.8H2c-.55 0-1-.45-1-1V3c0-.55.45-1 1-1h7c.55 0 1 .45 1 1v6.5l-.8-.8c-.39-.39-1.03-.39-1.42 0L5.7 10.8a.996.996 0 000 1.41v-.01zM4 4h5V3H4v1zm0 2h5V5H4v1zm0 2h3V7H4v1zM3 9H2v1h1V9zm0-2H2v1h1V7zm0-2H2v1h1V5zm0-2H2v1h1V3z"></path></svg>
<strong>Tip: </strong>Avoid using lambda as Getters during data processing in order to export the model correctly.
</div>
learn.export(fname='export.pkl') will lead to following Pickling error if <code>lambda</code> is used in the Data pipeline</p>
<pre><code>dsets = Datasets(concat_dsets, [[lambda x: x['image']], [lambda x: x['label'], Categorize]], splits=splits)</code></pre>
<p>PicklingError: Can't pickle <function <lambda> at 0x7f378c5aeaf0>: attribute lookup <lambda> on <strong>main</strong> failed</p>
<p>```</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">learn</span><span class="o">.</span><span class="n">export</span><span class="p">(</span><span class="n">fname</span><span class="o">=</span><span class="s1">'export.pkl'</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Inference">Inference<a class="anchor-link" href="#Inference"> </a></h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Now load the learner from the exported model. Predict the item ie image using <code>Learner.predict</code>. This function performs the necessary transforms on the item used as part of training using the learner.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">item</span><span class="p">,</span> <span class="n">expected</span> <span class="o">=</span> <span class="n">valid</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s1">'image'</span><span class="p">],</span> <span class="n">valid</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s1">'target'</span><span class="p">];</span> <span class="n">item</span><span class="p">,</span> <span class="n">expected</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>(<PIL.PngImagePlugin.PngImageFile image mode=L size=28x28>, 'Ankle boot')</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">learn</span><span class="o">.</span><span class="n">predict</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_html rendered_html output_subarea ">
<style>
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
progress:not([value]), progress:not([value])::-webkit-progress-bar {
background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
</style>
</div>
</div>
<div class="output_area">
<div class="output_html rendered_html output_subarea ">
</div>
</div>
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>('9',
tensor(9),
tensor([5.0262e-13, 4.2399e-12, 1.5671e-10, 1.6854e-12, 4.1097e-14, 1.6369e-06,
1.2831e-10, 1.0092e-05, 1.8003e-10, 9.9999e-01]))</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">learn</span><span class="o">.</span><span class="n">dls</span><span class="o">.</span><span class="n">after_item</span><span class="p">,</span> <span class="n">learn</span><span class="o">.</span><span class="n">dls</span><span class="o">.</span><span class="n">after_batch</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>(Pipeline: img2tensor,
Pipeline: IntToFloatTensor -- {'div': 255.0, 'div_mask': 1})</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Recreating-Learner.predict-from-the-source-code">Recreating <code>Learner.predict</code> from the source code<a class="anchor-link" href="#Recreating-Learner.predict-from-the-source-code"> </a></h3>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>We can run <code>learn.predict??</code> to examine what fastai does and review each line carefully.</p>
<pre><code>def predict(self, item, rm_type_tfms=None, with_input=False):
dl = self.dls.test_dl([item], rm_type_tfms=rm_type_tfms, num_workers=0)
inp,preds,_,dec_preds = self.get_preds(dl=dl, with_input=True, with_decoded=True)
i = getattr(self.dls, 'n_inp', -1)
inp = (inp,) if i==1 else tuplify(inp)
dec = self.dls.decode_batch(inp + tuplify(dec_preds))[0]
dec_inp,dec_targ = map(detuplify, [dec[:i],dec[i:]])
res = dec_targ,dec_preds[0],preds[0]
if with_input: res = (dec_inp,) + res
return res</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Converting the item by applying the transforms and create a dataloader out of it.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">dl</span> <span class="o">=</span> <span class="n">learn</span><span class="o">.</span><span class="n">dls</span><span class="o">.</span><span class="n">test_dl</span><span class="p">([</span><span class="n">item</span><span class="p">]);</span> <span class="n">dl</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre><fastai.data.core.TfmdDL></pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Internally <code>learn.predict</code> calls the <code>get_preds</code> method which accepts data loader and returns the input, predictions, the decoded predictions. This applies the same transforms done during training applied on the input during inference.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">inp</span><span class="p">,</span> <span class="n">preds</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">decoded_preds</span> <span class="o">=</span> <span class="n">learn</span><span class="o">.</span><span class="n">get_preds</span><span class="p">(</span><span class="n">dl</span><span class="o">=</span><span class="n">dl</span><span class="p">,</span> <span class="n">with_input</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">with_decoded</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_html rendered_html output_subarea ">
<style>
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
progress:not([value]), progress:not([value])::-webkit-progress-bar {
background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
</style>
</div>
</div>
<div class="output_area">
<div class="output_html rendered_html output_subarea ">
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Examine the input shape and type</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">inp</span><span class="o">.</span><span class="n">shape</span><span class="p">,</span> <span class="nb">type</span><span class="p">(</span><span class="n">inp</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>(torch.Size([1, 1, 28, 28]), fastai.torch_core.TensorImageBW)</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">tuplify</span><span class="p">(</span><span class="n">decoded_preds</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>(tensor([9]),)</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="nb">type</span><span class="p">(</span><span class="n">learn</span><span class="o">.</span><span class="n">dls</span><span class="o">.</span><span class="n">decode_batch</span><span class="p">((</span><span class="n">inp</span><span class="p">,)</span> <span class="o">+</span> <span class="n">tuplify</span><span class="p">(</span><span class="n">decoded_preds</span><span class="p">))),</span> <span class="nb">len</span><span class="p">(</span><span class="n">learn</span><span class="o">.</span><span class="n">dls</span><span class="o">.</span><span class="n">decode_batch</span><span class="p">((</span><span class="n">inp</span><span class="p">,)</span> <span class="o">+</span> <span class="n">tuplify</span><span class="p">(</span><span class="n">decoded_preds</span><span class="p">)))</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>(fastcore.foundation.L, 1)</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">image</span><span class="p">,</span> <span class="n">prediction</span> <span class="o">=</span> <span class="n">learn</span><span class="o">.</span><span class="n">dls</span><span class="o">.</span><span class="n">decode_batch</span><span class="p">((</span><span class="n">inp</span><span class="p">,)</span> <span class="o">+</span> <span class="n">tuplify</span><span class="p">(</span><span class="n">decoded_preds</span><span class="p">))[</span><span class="mi">0</span><span class="p">];</span> <span class="n">prediction</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>'9'</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">prediction</span><span class="p">,</span> <span class="n">decoded_preds</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>('9', tensor([9]))</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Let's examine fastai transforms done after item and after batch.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">learn</span><span class="o">.</span><span class="n">dls</span><span class="o">.</span><span class="n">after_item</span><span class="p">,</span> <span class="n">learn</span><span class="o">.</span><span class="n">dls</span><span class="o">.</span><span class="n">after_batch</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>(Pipeline: img2tensor,
Pipeline: IntToFloatTensor -- {'div': 255.0, 'div_mask': 1})</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">type_tfms</span> <span class="o">=</span> <span class="n">Pipeline</span><span class="p">([</span><span class="n">get_image_attr</span><span class="p">])</span>
<span class="n">item_tfms</span> <span class="o">=</span> <span class="n">Pipeline</span><span class="p">([</span><span class="n">img2tensor</span><span class="p">])</span>
<span class="n">batch_tfms</span> <span class="o">=</span> <span class="n">Pipeline</span><span class="p">([</span><span class="n">IntToFloatTensor</span><span class="p">])</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">train</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>{'image': <PIL.PngImagePlugin.PngImageFile image mode=L size=28x28>,
'label': 9,
'is_valid': False}</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">img</span> <span class="o">=</span> <span class="n">type_tfms</span><span class="p">(</span><span class="n">train</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span><span class="n">img</span><span class="o">.</span><span class="n">shape</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>(28, 28)</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">item_tfms</span><span class="p">(</span><span class="n">img</span><span class="p">)</span><span class="o">.</span><span class="n">shape</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>torch.Size([1, 28, 28])</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">batch_tfms</span><span class="p">(</span><span class="n">item_tfms</span><span class="p">(</span><span class="n">img</span><span class="p">)</span><span class="o">.</span><span class="n">cuda</span><span class="p">())</span><span class="o">.</span><span class="n">shape</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>torch.Size([1, 28, 28])</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>From the previous steps, we can uncover fastai magic such as transforms happening behind the scenes.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Gradio-app-deployment">Gradio app deployment<a class="anchor-link" href="#Gradio-app-deployment"> </a></h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Let's deploy the trained model and inference functionality in Gradio app and host the app in <a href="https://huggingface.co/spaces/msivanes">HuggingFace Space</a>.</p>
<p>Steps followed</p>
<ul>
<li>Create a new space in HF Space (Profile -> New Space)</li>
<li>Upload the exported model <code>export.pkl</code></li>
<li>Move all the necessary functions used as part of the transforms along with the inference provided below. This includes all the getters.</li>
<li>Add all the dependencies to <code>requirements.txt</code></li>
<li>Create a gradio interface passing the <code>classify</code> function, specifying the inputs(Image) and outputs(Label)</li>
<li>See the complete <a href="https://huggingface.co/spaces/msivanes/fashion-mnist-classifier/blob/main/app.py">Code</a> & <a href="https://huggingface.co/spaces/msivanes/fashion-mnist-classifier">Space</a></li>
</ul>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="kn">from</span> <span class="nn">fastai.vision.core</span> <span class="kn">import</span> <span class="n">PILImageBW</span><span class="p">,</span> <span class="n">TensorImageBW</span>
<span class="kn">from</span> <span class="nn">datasets</span> <span class="kn">import</span> <span class="n">ClassLabel</span>
<span class="kn">import</span> <span class="nn">gradio</span> <span class="k">as</span> <span class="nn">gr</span>
<span class="kn">from</span> <span class="nn">fastai.learner</span> <span class="kn">import</span> <span class="n">load_learner</span>
<span class="k">def</span> <span class="nf">get_image_attr</span><span class="p">(</span><span class="n">x</span><span class="p">):</span> <span class="k">return</span> <span class="n">x</span><span class="p">[</span><span class="s1">'image'</span><span class="p">]</span>
<span class="k">def</span> <span class="nf">get_target_attr</span><span class="p">(</span><span class="n">x</span><span class="p">):</span> <span class="k">return</span> <span class="n">x</span><span class="p">[</span><span class="s1">'target'</span><span class="p">]</span>
<span class="k">def</span> <span class="nf">img2tensor</span><span class="p">(</span><span class="n">im</span><span class="p">:</span> <span class="n">Image</span><span class="o">.</span><span class="n">Image</span><span class="p">):</span>
<span class="k">return</span> <span class="n">TensorImageBW</span><span class="p">(</span><span class="n">array</span><span class="p">(</span><span class="n">im</span><span class="p">))</span><span class="o">.</span><span class="n">unsqueeze</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="n">classLabel</span> <span class="o">=</span> <span class="n">ClassLabel</span><span class="p">(</span><span class="n">names</span><span class="o">=</span><span class="p">[</span><span class="s1">'T - shirt / top'</span><span class="p">,</span> <span class="s1">'Trouser'</span><span class="p">,</span> <span class="s1">'Pullover'</span><span class="p">,</span> <span class="s1">'Dress'</span><span class="p">,</span> <span class="s1">'Coat'</span><span class="p">,</span> <span class="s1">'Sandal'</span><span class="p">,</span> <span class="s1">'Shirt'</span><span class="p">,</span> <span class="s1">'Sneaker'</span><span class="p">,</span> <span class="s1">'Bag'</span><span class="p">,</span> <span class="s1">'Ankle boot'</span><span class="p">],</span> <span class="nb">id</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">add_target</span><span class="p">(</span><span class="n">x</span><span class="p">:</span><span class="nb">dict</span><span class="p">):</span>
<span class="n">x</span><span class="p">[</span><span class="s1">'target'</span><span class="p">]</span> <span class="o">=</span> <span class="n">classLabel</span><span class="o">.</span><span class="n">int2str</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="s1">'label'</span><span class="p">])</span>
<span class="k">return</span> <span class="n">x</span>
<span class="n">learn</span> <span class="o">=</span> <span class="n">load_learner</span><span class="p">(</span><span class="s1">'export.pkl'</span><span class="p">,</span> <span class="n">cpu</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">classify</span><span class="p">(</span><span class="n">inp</span><span class="p">):</span>
<span class="n">img</span> <span class="o">=</span> <span class="n">PILImageBW</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">inp</span><span class="p">)</span>
<span class="n">item</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">image</span><span class="o">=</span><span class="n">img</span><span class="p">)</span>
<span class="n">pred</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">learn</span><span class="o">.</span><span class="n">predict</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
<span class="k">return</span> <span class="n">classLabel</span><span class="o">.</span><span class="n">int2str</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">pred</span><span class="p">))</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">fname</span><span class="o">=</span><span class="s1">'shoes.jpg'</span>
<span class="n">classify</span><span class="p">(</span><span class="n">fname</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_html rendered_html output_subarea ">
<style>
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
progress:not([value]), progress:not([value])::-webkit-progress-bar {
background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
</style>
</div>
</div>
<div class="output_area">
<div class="output_html rendered_html output_subarea ">
</div>
</div>
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>'Ankle boot'</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing code_cell rendered">
<div class="input">
<div class="inner_cell">
<div class="input_area">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">fname1</span> <span class="o">=</span> <span class="s1">'t-shirt.jpg'</span>
<span class="n">classify</span><span class="p">(</span><span class="n">fname1</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="output_wrapper">
<div class="output">
<div class="output_area">
<div class="output_html rendered_html output_subarea ">
<style>
/* Turns off some styling */
progress {
/* gets rid of default border in Firefox and Opera. */
border: none;
/* Needs to be in here for Safari polyfill so background images work as expected. */
background-size: auto;
}
progress:not([value]), progress:not([value])::-webkit-progress-bar {
background: repeating-linear-gradient(45deg, #7e7e7e, #7e7e7e 10px, #5c5c5c 10px, #5c5c5c 20px);
}
.progress-bar-interrupted, .progress-bar-interrupted::-webkit-progress-bar {
background: #F44336;
}
</style>
</div>
</div>
<div class="output_area">
<div class="output_html rendered_html output_subarea ">
</div>
</div>
<div class="output_area">
<div class="output_text output_subarea output_execute_result">
<pre>'T - shirt / top'</pre>
</div>
</div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Note: This is my project write up for WalkWithFastai revisited course as one of my goal for this course is to get comfortable with low level API, debug issues diving into the source, uncovering the fastai magic. Thanks to Zach Mueller for an excellent course.</p>
<h2 id="References">References<a class="anchor-link" href="#References"> </a></h2><ul>
<li><a href="https://store.walkwithfastai.com/walk-with-fastai-revisited">https://store.walkwithfastai.com/walk-with-fastai-revisited</a> </li>
<li><a href="https://walkwithfastai.com/MNIST">https://walkwithfastai.com/MNIST</a> </li>
<li><a href="https://github.com/fastai/fastbook/blob/master/11_midlevel_data.ipynb">https://github.com/fastai/fastbook/blob/master/11_midlevel_data.ipynb</a></li>
</ul>
</div>
</div>
</div>
</div>
<script type="application/vnd.jupyter.widget-state+json">
{"00b51412708844e0abe8f5f35f29ef22": {"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}}, "018f264e726c45799169370f87a62844": {"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_454e0f337363449bb347e33086f869bb", "placeholder": "\u200b", "style": "IPY_MODEL_748b9e23407e4ac79696d0e612471b24", "value": "Map: 99%"}}, "028f92891977495382b2f83ca8a3f80d": {"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_65f311b5dbdd414799a20955d941b551", "max": 5148, "min": 0, "orientation": "horizontal", "style": "IPY_MODEL_22b3553ee03c45b9a0830360a51fba10", "value": 5148}}, "04d7fbcdce774c7993d36b2dbbb70181": {"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}}, "04dca9928970428fb20936f3fab23239": {"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": ""}}, "05b98d02955d44ac8c9dc4304ba94910": {"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": ""}}, "0675040429134a45b5fb7d286246fa9b": {"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": ""}}, "07c1029050594da984656e12f4c8cb93": {"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_3ab200ca298849c69fc2a79b30c5c7cd", "placeholder": "\u200b", "style": "IPY_MODEL_74d5dceb813c40f8b6fee56c2f5c4658", "value": " 5.15k/5.15k [00:00<00:00, 264kB/s]"}}, "0bd6c39eefeb4bb8bf17637512f1677f": {"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_817ee6b299884296b3cbb10eb86d46f3", "IPY_MODEL_2ab35f7656434dd78c7591f9b134451f", "IPY_MODEL_2c713d601800496687895db49def01dd"], "layout": "IPY_MODEL_a58034a9efc444649cb48a06169f1799"}}, "0ce3375435944beb9a9ddaf24b9191df": {"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_3652aa2b865e47b1b7258fed2527ac5b", "placeholder": "\u200b", "style": "IPY_MODEL_0d3fec1d61f448829b6fd40cc26580a5", "value": " 2/2 [00:00<00:00, 69.40it/s]"}}, "0d3fec1d61f448829b6fd40cc26580a5": {"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": ""}}, "0e62386252254ab2b13a4a90aebc560e": {"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": "", "description": "", "description_tooltip": null, "layout": "IPY_MODEL_6b60d40fb6b04749ba7da8aedc4cc0d6", "max": 60000, "min": 0, "orientation": "horizontal", "style": "IPY_MODEL_457d35ada67c4ab3af8b0fdd01f6e79d", "value": 60000}}, "11eed35723bb43a99fea55a28c376106": {"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": ""}}, "11f159ae40374c8296e3c3695856939f": {"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_d520969c1603475da55a3eaa5af48c3f", "placeholder": "\u200b", "style": "IPY_MODEL_23e0404b8ff0454a91319bd4a5680387", "value": " 8.85k/8.85k [00:00<00:00, 274kB/s]"}}, "12aec319657643138a451ccee373a1d3": {"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}}, "1438b390703346288c45e15ccf32d8ba": {"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_304cfd57ac574351890b037bb8175f3d", "IPY_MODEL_3ffbe917866743788fd37fea97bbb001", "IPY_MODEL_ea692d0dfac4466299015180715c1c7b"], "layout": "IPY_MODEL_177dddf78d6f4b1ea9243512c8e7d800"}}, "15ca6b72fb8f425da30e75fe40abc20e": {"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_af28b46d0a874f9eab3a3c7961cee034", "max": 3126, "min": 0, "orientation": "horizontal", "style": "IPY_MODEL_1fce2fb22dd74a9486dcfd6cbb1f2449", "value": 3126}}, "16b64cd6eb774fb181e1da63380cf7e9": {"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_c429847840b64cebae4752e3fe92a41d", "placeholder": "\u200b", "style": "IPY_MODEL_bc4576a874864d1babb8e74e43cd93dc", "value": "Generating train split: 100%"}}, "177dddf78d6f4b1ea9243512c8e7d800": {"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}}, "1d2ba866fdc542e7ab369cdbc944c18f": {"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_4a73fc68636041e887f6240034294919", "placeholder": "\u200b", "style": "IPY_MODEL_852ab64c347d4920bad26e95333cdc85", "value": "Downloading data: 100%"}}, "1ea3877f59e94c43adab44deba70295c": {"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": ""}}, "1f55f1383d13442fb64b69c28fe1c66d": {"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}}, "1fce2fb22dd74a9486dcfd6cbb1f2449": {"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": ""}}, "219c3e7b1b5b47d49374ff01fc8470a9": {"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}}, "22b3553ee03c45b9a0830360a51fba10": {"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": ""}}, "2387dfe5b02f40a389adb5628bed6f0d": {"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": ""}}, "23e0404b8ff0454a91319bd4a5680387": {"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": ""}}, "25063cd358854736b455ddc6eaa99f12": {"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}}, "25468d53b20042d19586dcb2335fda25": {"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}}, "25c03ecb3fa6492a992a38dd808786aa": {"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}}, "28dd0aab42484898b4bd6098dd9a951e": {"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": ""}}, "2a6575eeee694038a6df41daa6a5e555": {"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}}, "2ab35f7656434dd78c7591f9b134451f": {"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": "", "description": "", "description_tooltip": null, "layout": "IPY_MODEL_4a202ed5d09d4a67af396595c7a6f924", "max": 10000, "min": 0, "orientation": "horizontal", "style": "IPY_MODEL_28dd0aab42484898b4bd6098dd9a951e", "value": 10000}}, "2c188e64633a44449b3668ea3fe6a9fe": {"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}}, "2c713d601800496687895db49def01dd": {"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_7dbfc92b465a477087769d9bff6c17e9", "placeholder": "\u200b", "style": "IPY_MODEL_cc151c7043f4459db4c653648bdeebf6", "value": " 8000/10000 [00:00<00:00, 21298.31 examples/s]"}}, "2ca8782780664144b889356656b8dd28": {"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": ""}}, "2d1b64d199c34eaea338efa9ff356d6e": {"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_709ea4ac49364d84b13f4b4fa0dc2cfa", "IPY_MODEL_577184bb176c446dbab369e5480ff2d3", "IPY_MODEL_7502430c22814ddca76fcc363d8bf0f1"], "layout": "IPY_MODEL_6c35df39190c42b49216ffad2e4f0d02"}}, "2d5a27c7792643f48f95d14ef9b353f7": {"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_25468d53b20042d19586dcb2335fda25", "placeholder": "\u200b", "style": "IPY_MODEL_5bb2701747aa4436a1fb999dc5102863", "value": " 60000/60000 [00:33<00:00, 4275.89 examples/s]"}}, "2e9fc20a23344610853b10882aaee3fa": {"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": ""}}, "30009b084bd0449c96e4212047283d0e": {"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_16b64cd6eb774fb181e1da63380cf7e9", "IPY_MODEL_acf009b55f4740e7b72240da0ca3c864", "IPY_MODEL_2d5a27c7792643f48f95d14ef9b353f7"], "layout": "IPY_MODEL_f4812cc9fb22494a842c8c0382aae873"}}, "304cfd57ac574351890b037bb8175f3d": {"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_3aaa20b34416480b9f9aa5fa3ab840bb", "placeholder": "\u200b", "style": "IPY_MODEL_639fd2994cdd4ee3bcc1f7a3db823267", "value": "Downloading data: 100%"}}, "30b9e9bf858748219d250a76a80f11a7": {"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_367906a7df42470d8db1446725ff09ef", "IPY_MODEL_7ff552ae55284ff7a5b0dd960db73983", "IPY_MODEL_702ec3d7997b43aba578ea9929c6f00d"], "layout": "IPY_MODEL_84a18c3c8bef4ce1978fd45362843643"}}, "30feaa4312794ab884742160a83e8d81": {"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": ""}}, "331d5b088f2842e69808f7edcc94d57f": {"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}}, "347038d62e914bdea97de3de91b47d90": {"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_74190f3fb5304045a289263c168142cd", "placeholder": "\u200b", "style": "IPY_MODEL_a5c5c866ca8045f7a72f331713ecb8de", "value": "Downloading data: 100%"}}, "3652aa2b865e47b1b7258fed2527ac5b": {"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}}, "367906a7df42470d8db1446725ff09ef": {"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_2c188e64633a44449b3668ea3fe6a9fe", "placeholder": "\u200b", "style": "IPY_MODEL_3bdcdd03ebfd4ef08882ef9728dfba41", "value": "Generating test split: 100%"}}, "376b276950c9444caec4ee36cb34e462": {"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}}, "386f1703a5654e5b91518c48def6b6ab": {"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_376b276950c9444caec4ee36cb34e462", "placeholder": "\u200b", "style": "IPY_MODEL_5b9b99796b1441c6a7f559c4d5900661", "value": "Downloading metadata: 100%"}}, "3aaa20b34416480b9f9aa5fa3ab840bb": {"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}}, "3ab200ca298849c69fc2a79b30c5c7cd": {"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}}, "3bdcdd03ebfd4ef08882ef9728dfba41": {"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": ""}}, "3c6d78d8cb0d40f5b3eb65e8bf684e0b": {"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_219c3e7b1b5b47d49374ff01fc8470a9", "max": 4, "min": 0, "orientation": "horizontal", "style": "IPY_MODEL_11eed35723bb43a99fea55a28c376106", "value": 4}}, "3f38af79268149908d222290497d5626": {"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": "hidden", "width": null}}, "3ffbe917866743788fd37fea97bbb001": {"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_9826fce849874ff9adf04cdf76e76aee", "max": 26421880, "min": 0, "orientation": "horizontal", "style": "IPY_MODEL_a6a9ed7043f843f29b32402c000ab033", "value": 26421880}}, "454e0f337363449bb347e33086f869bb": {"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}}, "457d35ada67c4ab3af8b0fdd01f6e79d": {"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": ""}}, "45c62957cccb419ebe528edb961a6be0": {"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}}, "46b83ef707034014bd4348607c0f64c8": {"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}}, "4a202ed5d09d4a67af396595c7a6f924": {"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}}, "4a73fc68636041e887f6240034294919": {"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}}, "4aea9513a38e4f2c922dab2d425996d9": {"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_f2d5f75c3f104680816777c991c8bbfa", "placeholder": "\u200b", "style": "IPY_MODEL_0675040429134a45b5fb7d286246fa9b", "value": " 4/4 [00:04<00:00, 1.06it/s]"}}, "52b8d271d4854c3f8d365ae2103b31b3": {"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_12aec319657643138a451ccee373a1d3", "placeholder": "\u200b", "style": "IPY_MODEL_1ea3877f59e94c43adab44deba70295c", "value": " 59605/60000 [00:02<00:00, 22366.05 examples/s]"}}, "5347baaed47c471fbc927c13e1c85629": {"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_ab3c4df398dd4f1b9fb8179f30431f36", "IPY_MODEL_3c6d78d8cb0d40f5b3eb65e8bf684e0b", "IPY_MODEL_4aea9513a38e4f2c922dab2d425996d9"], "layout": "IPY_MODEL_99c9acb1d8d343a882eb7d9914dae2d0"}}, "55f5f7dbcb944dc8961aabdd9ca163b0": {"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}}, "577184bb176c446dbab369e5480ff2d3": {"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_25063cd358854736b455ddc6eaa99f12", "max": 4, "min": 0, "orientation": "horizontal", "style": "IPY_MODEL_98cc26820baa4d928c25ca35bc9c84f5", "value": 4}}, "57e47f8ddc19435799d67cb8c6b57b43": {"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}}, "58db6503d01c4c3099e93fc6d2bba36b": {"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}}, "59f5798cab7f4663a61384160639aef2": {"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}}, "5b464835362a45629ef1e57bdd89e0e4": {"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_45c62957cccb419ebe528edb961a6be0", "placeholder": "\u200b", "style": "IPY_MODEL_2ca8782780664144b889356656b8dd28", "value": " 4.83k/4.83k [00:00<00:00, 264kB/s]"}}, "5b9b99796b1441c6a7f559c4d5900661": {"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": ""}}, "5bb2701747aa4436a1fb999dc5102863": {"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": ""}}, "5c95bc60a01c48248c362cf5aef78962": {"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": ""}}, "639fd2994cdd4ee3bcc1f7a3db823267": {"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": ""}}, "65f311b5dbdd414799a20955d941b551": {"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}}, "67de911a8cd84a84baf0b87ca51785cb": {"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}}, "696d5e0f7642435c8fd3293760da76ed": {"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}}, "6b60d40fb6b04749ba7da8aedc4cc0d6": {"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}}, "6c35df39190c42b49216ffad2e4f0d02": {"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}}, "6de8cbb415644686a5ad9c782cae33e3": {"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_386f1703a5654e5b91518c48def6b6ab", "IPY_MODEL_15ca6b72fb8f425da30e75fe40abc20e", "IPY_MODEL_798e46a7232d41d6a4115fb4b4ee1bd0"], "layout": "IPY_MODEL_810291800e97485793f22e52d611082f"}}, "702ec3d7997b43aba578ea9929c6f00d": {"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_1f55f1383d13442fb64b69c28fe1c66d", "placeholder": "\u200b", "style": "IPY_MODEL_7f65a7c34b2f4d939755aeedfb17ef45", "value": " 10000/10000 [00:15<00:00, 5913.89 examples/s]"}}, "709ea4ac49364d84b13f4b4fa0dc2cfa": {"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_93a63dd9c7464272b381145bb2edd49f", "placeholder": "\u200b", "style": "IPY_MODEL_2e9fc20a23344610853b10882aaee3fa", "value": "Extracting data files: 100%"}}, "74190f3fb5304045a289263c168142cd": {"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}}, "744d6e085ebd4aeba8d2ae9221ebeaa8": {"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_c9702942938442849cf1becbf5953bd4", "IPY_MODEL_f4447048082f4f7b818d663078fc1b22", "IPY_MODEL_0ce3375435944beb9a9ddaf24b9191df"], "layout": "IPY_MODEL_00b51412708844e0abe8f5f35f29ef22"}}, "748b9e23407e4ac79696d0e612471b24": {"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": ""}}, "74d5dceb813c40f8b6fee56c2f5c4658": {"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": ""}}, "7502430c22814ddca76fcc363d8bf0f1": {"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_696d5e0f7642435c8fd3293760da76ed", "placeholder": "\u200b", "style": "IPY_MODEL_2387dfe5b02f40a389adb5628bed6f0d", "value": " 4/4 [00:00<00:00, 5.65it/s]"}}, "778bbdb9ec8e4906b12cf15253e77d5f": {"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_e393a20b01b8491ebda86b9c5f50a335", "max": 29515, "min": 0, "orientation": "horizontal", "style": "IPY_MODEL_5c95bc60a01c48248c362cf5aef78962", "value": 29515}}, "798e46a7232d41d6a4115fb4b4ee1bd0": {"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_eaa08b4ab8c94efab2bc74004927d05f", "placeholder": "\u200b", "style": "IPY_MODEL_e5d209c702d847148e06c7466ac75b00", "value": " 3.13k/3.13k [00:00<00:00, 195kB/s]"}}, "7d31e47bd54d4ec58dcf79fa9fff7693": {"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_2a6575eeee694038a6df41daa6a5e555", "placeholder": "\u200b", "style": "IPY_MODEL_c2eb12027f53436e9c3e874af848e8e1", "value": "Downloading builder script: 100%"}}, "7d90f97f03b84bcbbd9f5b8c9faaa0dd": {"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": ""}}, "7dbfc92b465a477087769d9bff6c17e9": {"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}}, "7ec29a590c234f09ab0ad4c2df41eb8b": {"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_7d31e47bd54d4ec58dcf79fa9fff7693", "IPY_MODEL_9b6729da1ec64786934b704d6ecebab1", "IPY_MODEL_5b464835362a45629ef1e57bdd89e0e4"], "layout": "IPY_MODEL_dd95129e299f401cad1997e657f03963"}}, "7f65a7c34b2f4d939755aeedfb17ef45": {"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": ""}}, "7fdd83c809f64b3aaabce750dbce3050": {"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": ""}}, "7ff552ae55284ff7a5b0dd960db73983": {"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": "", "description": "", "description_tooltip": null, "layout": "IPY_MODEL_ad28842caa61442f9395d5906b33e080", "max": 10000, "min": 0, "orientation": "horizontal", "style": "IPY_MODEL_7fdd83c809f64b3aaabce750dbce3050", "value": 10000}}, "810291800e97485793f22e52d611082f": {"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}}, "817ee6b299884296b3cbb10eb86d46f3": {"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_331d5b088f2842e69808f7edcc94d57f", "placeholder": "\u200b", "style": "IPY_MODEL_30feaa4312794ab884742160a83e8d81", "value": "Map: 80%"}}, "84a18c3c8bef4ce1978fd45362843643": {"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": "hidden", "width": null}}, "852ab64c347d4920bad26e95333cdc85": {"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": ""}}, "86005de9b9aa4928baa75eaf29361fe2": {"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": ""}}, "87246dde54db4e18950a24a39da56003": {"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}}, "88156e676c994a5eb13ea461b84b33b5": {"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": ""}}, "895c18f7051541c8b3e5d72e08f72bba": {"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_b02a0c4ff0c44eabbc342acd661d6f3c", "placeholder": "\u200b", "style": "IPY_MODEL_ecbb8c625bf04ac0b965d91f09ef0831", "value": " 29.5k/29.5k [00:00<00:00, 640kB/s]"}}, "8c2c97025f184ce29a19ed9060386fcf": {"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_a4986c8d09ed4256bf1345d797647989", "IPY_MODEL_028f92891977495382b2f83ca8a3f80d", "IPY_MODEL_07c1029050594da984656e12f4c8cb93"], "layout": "IPY_MODEL_9d53a724d9f54407b56df70a24f2b21a"}}, "8d23560db1dc4573801df196b7083b5b": {"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}}, "92d89f32a4ad4a998275b29a1bc65268": {"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": ""}}, "93360ac4309943f7a6abcfde06455235": {"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_67de911a8cd84a84baf0b87ca51785cb", "max": 4422102, "min": 0, "orientation": "horizontal", "style": "IPY_MODEL_d1df149054d14c03818a30570594cdec", "value": 4422102}}, "93a63dd9c7464272b381145bb2edd49f": {"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}}, "9826fce849874ff9adf04cdf76e76aee": {"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}}, "98cc26820baa4d928c25ca35bc9c84f5": {"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": ""}}, "9975f307cfea46aeae684d8db6726cf3": {"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_87246dde54db4e18950a24a39da56003", "placeholder": "\u200b", "style": "IPY_MODEL_04dca9928970428fb20936f3fab23239", "value": "100%"}}, "99c9acb1d8d343a882eb7d9914dae2d0": {"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}}, "99e3809805654a469524c3ea05cb8735": {"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_1d2ba866fdc542e7ab369cdbc944c18f", "IPY_MODEL_93360ac4309943f7a6abcfde06455235", "IPY_MODEL_aede0c7b52ce4357b25740208d844e9e"], "layout": "IPY_MODEL_f3053b069bd342a3bab5fc28063f831b"}}, "9b6729da1ec64786934b704d6ecebab1": {"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_55f5f7dbcb944dc8961aabdd9ca163b0", "max": 4833, "min": 0, "orientation": "horizontal", "style": "IPY_MODEL_05b98d02955d44ac8c9dc4304ba94910", "value": 4833}}, "9d53a724d9f54407b56df70a24f2b21a": {"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}}, "a0569a9b1cf9487aa683b95071d8c433": {"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_018f264e726c45799169370f87a62844", "IPY_MODEL_0e62386252254ab2b13a4a90aebc560e", "IPY_MODEL_52b8d271d4854c3f8d365ae2103b31b3"], "layout": "IPY_MODEL_3f38af79268149908d222290497d5626"}}, "a4986c8d09ed4256bf1345d797647989": {"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_58db6503d01c4c3099e93fc6d2bba36b", "placeholder": "\u200b", "style": "IPY_MODEL_d04a95ed07d54ae093d1fed86517ec64", "value": "Downloading data: 100%"}}, "a58034a9efc444649cb48a06169f1799": {"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": "hidden", "width": null}}, "a5c5c866ca8045f7a72f331713ecb8de": {"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": ""}}, "a6a9ed7043f843f29b32402c000ab033": {"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": ""}}, "aa3b574e9e8f4fce979e54a5c34f4b05": {"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}}, "ab05d3456fcd4caeba9d83eb8bdfaf7e": {"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}}, "ab3c4df398dd4f1b9fb8179f30431f36": {"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_b0e17a42336c44e5ae9ac55560f30181", "placeholder": "\u200b", "style": "IPY_MODEL_be974aaa98e34a5c84d8cd5d13aebb3d", "value": "Downloading data files: 100%"}}, "acf009b55f4740e7b72240da0ca3c864": {"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": "", "description": "", "description_tooltip": null, "layout": "IPY_MODEL_d80ee691b1904fe38f37f44d0d94e4a1", "max": 60000, "min": 0, "orientation": "horizontal", "style": "IPY_MODEL_7d90f97f03b84bcbbd9f5b8c9faaa0dd", "value": 60000}}, "ad28842caa61442f9395d5906b33e080": {"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}}, "aede0c7b52ce4357b25740208d844e9e": {"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_d75a44cdee424200ad648052df50563e", "placeholder": "\u200b", "style": "IPY_MODEL_88156e676c994a5eb13ea461b84b33b5", "value": " 4.42M/4.42M [00:00<00:00, 12.8MB/s]"}}, "af28b46d0a874f9eab3a3c7961cee034": {"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}}, "b02a0c4ff0c44eabbc342acd661d6f3c": {"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}}, "b0e17a42336c44e5ae9ac55560f30181": {"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}}, "b32206e9ad0a418da78caa4721b24b9a": {"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_9975f307cfea46aeae684d8db6726cf3", "IPY_MODEL_b87abc93817f47c2a9308f0e7aa98743", "IPY_MODEL_e0aa406d7b924db9b6c6e1ae5acd43a3"], "layout": "IPY_MODEL_8d23560db1dc4573801df196b7083b5b"}}, "b39e9cdc733f4851b61e20c3d961b980": {"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": ""}}, "b87abc93817f47c2a9308f0e7aa98743": {"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_25c03ecb3fa6492a992a38dd808786aa", "max": 87319819, "min": 0, "orientation": "horizontal", "style": "IPY_MODEL_d2bacac9e7dd496ab0b7454074dad9e8", "value": 87319819}}, "bc4576a874864d1babb8e74e43cd93dc": {"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": ""}}, "be974aaa98e34a5c84d8cd5d13aebb3d": {"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": ""}}, "c2eb12027f53436e9c3e874af848e8e1": {"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": ""}}, "c429847840b64cebae4752e3fe92a41d": {"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}}, "c51d670b8d1b46e3bfce80faedcbd40b": {"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_d56da8585aaa4b6d88fb907878af3d95", "IPY_MODEL_e9c68df3c7d047d5b49bc8bf00e5b44b", "IPY_MODEL_11f159ae40374c8296e3c3695856939f"], "layout": "IPY_MODEL_46b83ef707034014bd4348607c0f64c8"}}, "c9702942938442849cf1becbf5953bd4": {"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_cca45c02ec144fba8733174333c877e4", "placeholder": "\u200b", "style": "IPY_MODEL_92d89f32a4ad4a998275b29a1bc65268", "value": "100%"}}, "cc151c7043f4459db4c653648bdeebf6": {"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": ""}}, "cc6ea7ae3aac47938f2b186fe4563b95": {"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_347038d62e914bdea97de3de91b47d90", "IPY_MODEL_778bbdb9ec8e4906b12cf15253e77d5f", "IPY_MODEL_895c18f7051541c8b3e5d72e08f72bba"], "layout": "IPY_MODEL_57e47f8ddc19435799d67cb8c6b57b43"}}, "cca45c02ec144fba8733174333c877e4": {"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}}, "d04a95ed07d54ae093d1fed86517ec64": {"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": ""}}, "d1df149054d14c03818a30570594cdec": {"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": ""}}, "d2bacac9e7dd496ab0b7454074dad9e8": {"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": ""}}, "d3a0bbe167194fd2a9b50221f6c7d6e7": {"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": ""}}, "d520969c1603475da55a3eaa5af48c3f": {"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}}, "d56da8585aaa4b6d88fb907878af3d95": {"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_ab05d3456fcd4caeba9d83eb8bdfaf7e", "placeholder": "\u200b", "style": "IPY_MODEL_b39e9cdc733f4851b61e20c3d961b980", "value": "Downloading readme: 100%"}}, "d75a44cdee424200ad648052df50563e": {"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}}, "d80ee691b1904fe38f37f44d0d94e4a1": {"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}}, "d94852e6460848ef873b263eb8a78929": {"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}}, "db042b65bb9449fca1f08d97c748d9e3": {"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": ""}}, "dd95129e299f401cad1997e657f03963": {"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}}, "e0aa406d7b924db9b6c6e1ae5acd43a3": {"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_04d7fbcdce774c7993d36b2dbbb70181", "placeholder": "\u200b", "style": "IPY_MODEL_fd8603c855ee44c188dccb95eafd8716", "value": " 83.3M/83.3M [00:00<00:00, 160MB/s]"}}, "e393a20b01b8491ebda86b9c5f50a335": {"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}}, "e5d209c702d847148e06c7466ac75b00": {"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": ""}}, "e9c68df3c7d047d5b49bc8bf00e5b44b": {"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_d94852e6460848ef873b263eb8a78929", "max": 8845, "min": 0, "orientation": "horizontal", "style": "IPY_MODEL_86005de9b9aa4928baa75eaf29361fe2", "value": 8845}}, "ea692d0dfac4466299015180715c1c7b": {"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_aa3b574e9e8f4fce979e54a5c34f4b05", "placeholder": "\u200b", "style": "IPY_MODEL_d3a0bbe167194fd2a9b50221f6c7d6e7", "value": " 26.4M/26.4M [00:00<00:00, 38.2MB/s]"}}, "eaa08b4ab8c94efab2bc74004927d05f": {"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}}, "ecbb8c625bf04ac0b965d91f09ef0831": {"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": ""}}, "f2d5f75c3f104680816777c991c8bbfa": {"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}}, "f3053b069bd342a3bab5fc28063f831b": {"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}}, "f4447048082f4f7b818d663078fc1b22": {"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_59f5798cab7f4663a61384160639aef2", "max": 2, "min": 0, "orientation": "horizontal", "style": "IPY_MODEL_db042b65bb9449fca1f08d97c748d9e3", "value": 2}}, "f4812cc9fb22494a842c8c0382aae873": {"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": "hidden", "width": null}}, "fd8603c855ee44c188dccb95eafd8716": {"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": ""}}}
</script>
</lambda></lambda></p></div></div></div></div>Poetry First Impressions2021-01-09T00:00:00-06:002021-01-09T00:00:00-06:00https://manisnesan.github.io/chrestotes/python/reproducibility/2021/01/09/poetry-first-impressions<h1 id="poetry-first-impressions">Poetry First Impressions</h1>
<p>Recently I inherited a python project which did not have dependency management setup and this post is a summary of my investigation using Poetry.</p>
<h2 id="issues-happening-in-the-project">Issues happening in the project</h2>
<ul>
<li>Different python versions used by developers and in production.</li>
<li>setup.py not maintained</li>
<li>Differentiating the dev dependencies vs production dependencies is hard with a single requirements.txt file</li>
<li>Tracking the transitive dependencies.</li>
<li>Locking the dependencies when we are ready to push the code.</li>
</ul>
<h2 id="key-requirements">Key Requirements</h2>
<ul>
<li>Reproducibility and Consistency are the key aspects for maintaining the project.</li>
<li>Managing dependencies in a python project and relying on a single tool (eg: pip, conda)</li>
</ul>
<h3 id="test-drive-with-poetry">Test Drive with Poetry</h3>
<ul>
<li><a href="https://python-poetry.org/docs/">Poetry</a></li>
</ul>
<blockquote>
<p>Poetry is a tool for dependency management and packaging in Python. It allows you to declare the libraries your project depends on and it will manage (install/update) them for you.</p>
</blockquote>
<ul>
<li>Getting Started on Linux</li>
</ul>
<p><code class="highlighter-rouge">$ curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -
</code></p>
<ul>
<li>
<p>To start a new project <code class="highlighter-rouge">poetry new <project-name></code>. If you have an existing project then <code class="highlighter-rouge">poetry init</code> - guide you through setting a project specific pyproject.toml config.</p>
<ol>
<li>Package, version, description, author, compatible versions</li>
<li>Main Dependencies</li>
<li>Development Dependencies</li>
</ol>
</li>
<li>
<p>Format of pyproject.toml config</p>
<div class="language-toml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">[tool.poetry]</span>
<span class="py">name</span> <span class="p">=</span> <span class="s">"language-detection"</span>
<span class="py">version</span> <span class="p">=</span> <span class="s">"0.1.0"</span>
<span class="py">description</span> <span class="p">=</span> <span class="s">"Detects the language of the provided text using fasttext."</span>
<span class="py">authors</span> <span class="p">=</span> <span class="p">[</span><span class="s">"Your Name <you@example.com>"</span><span class="p">]</span>
<span class="nn">[tool.poetry.dependencies]</span>
<span class="py">python</span> <span class="p">=</span> <span class="s">"^3.6"</span>
<span class="py">fasttext</span> <span class="p">=</span> <span class="s">"0.9.1"</span>
<span class="py">Flask</span> <span class="p">=</span> <span class="s">"1.1.1"</span>
<span class="py">gunicorn</span> <span class="p">=</span> <span class="s">"20.0.4"</span>
<span class="nn">[tool.poetry.dev-dependencies]</span>
<span class="py">codecov</span> <span class="p">=</span> <span class="s">"2.1.7"</span>
<span class="py">flake8</span> <span class="p">=</span> <span class="s">"^3.8.4"</span>
<span class="py">black</span> <span class="p">=</span> <span class="s">"^20.8b1"</span>
<span class="py">pytest</span> <span class="p">=</span> <span class="s">"^6.2.1"</span>
<span class="py">pytest-cov</span> <span class="p">=</span> <span class="s">"^2.10.1"</span>
<span class="nn">[build-system]</span>
<span class="py">requires</span> <span class="p">=</span> <span class="nn">["poetry-core>=1.0.0"]</span>
<span class="py">build-backend</span> <span class="p">=</span> <span class="s">"poetry.core.masonry.api"</span>
</code></pre></div> </div>
</li>
<li>
<p>Manage virtual environments - Poetry automatically creates a virtual environments for you based on the project when you ran <em>new</em> or <em>init</em>. You can know more info using the following commands & use either <code class="highlighter-rouge">poetry shell</code> or <code class="highlighter-rouge">source <cache_dir>/pypoetry/virtualenvs/<project_venv>/bin/activate</code> to activate the environment. <code class="highlighter-rouge">deactivate</code> if you want to exit the environment.</p>
</li>
</ul>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ poetry env info
Virtualenv
Python: 3.8.6
Implementation: CPython
Path: /home/msivanes/.cache/pypoetry/virtualenvs/language-detection-ddSi-Wir-py3.8
Valid: True
System
Platform: linux
OS: posix
Python: /usr
$ poetry config --list
cache-dir = "/home/msivanes/.cache/pypoetry"
experimental.new-installer = true
installer.parallel = true
virtualenvs.create = true
virtualenvs.in-project = null
virtualenvs.path = "{cache-dir}/virtualenvs" # /home/msivanes/.cache/pypoetry/virtualenvs
</code></pre></div></div>
<ul>
<li>
<p>Add dependency through <code class="highlighter-rouge">poetry add <package></code> or <code class="highlighter-rouge">poetry add <package>@<version></code></p>
<p><code class="highlighter-rouge">$ poetry add Flask</code></p>
<p><code class="highlighter-rouge">$ poetry add fasttext@0.9.1</code></p>
<p><code class="highlighter-rouge">$ poetry add pytest</code></p>
</li>
<li>
<p>Remove a dependency using <code class="highlighter-rouge">poetry remove <package></code></p>
<p><code class="highlighter-rouge">$ poetry remove pyfasttext</code></p>
</li>
<li>
<p>Once you finish adding the dependencies, run <code class="highlighter-rouge">poetry install</code> to install all the dependencies in your project. This will generate the <em>poetry.lock</em> file. This is where all the dependencies are locked and needs to be version controlled. If any other developer run <code class="highlighter-rouge">poetry install</code> then poetry uses the exact same versions specified in the dependencies while installing. This ensures all the developers are using a consistent dependencies across the board.</p>
</li>
<li>
<p>If you want to upgrade the dependencies and use the latest versions, then use <code class="highlighter-rouge">poetry update</code>. This is the equivalent of deleting the poetry.lock and using <em>install</em> .</p>
</li>
<li>
<p>Exporting the requirements.txt if you want to containarize your app.</p>
<p><code class="highlighter-rouge">$ poetry export --without-hashes -f requirements.txt > requirements.txt</code></p>
</li>
<li>
<p>For scenarios in libraries where you want to perform an editable install and hence you need a setup.py file. (Github user <a href="https://github.com/albireox">@albireox</a> provided a script to quickly create setup.py which I found it <a href="https://github.com/python-poetry/poetry/issues/761#issuecomment-678113547">here</a></p>
</li>
</ul>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# @Author: José Sánchez-Gallego (gallegoj@uw.edu)
# @Date: 2019-12-18
# @Filename: create_setup.py
# @License: BSD 3-clause (http://www.opensource.org/licenses/BSD-3-Clause)
</span>
<span class="c1"># This is a temporary solution for the fact that pip install . fails with
# poetry when there is no setup.py and an extension needs to be compiled.
# See https://github.com/python-poetry/poetry/issues/1516. Running this
# script creates a setup.py filled out with information generated by
# poetry when parsing the pyproject.toml.
</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">from</span> <span class="nn">distutils.version</span> <span class="kn">import</span> <span class="n">StrictVersion</span>
<span class="c1"># If there is a global installation of poetry, prefer that.
</span><span class="n">lib</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">expanduser</span><span class="p">(</span><span class="s">'~/.poetry/lib'</span><span class="p">)</span>
<span class="n">vendors</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">lib</span><span class="p">,</span> <span class="s">'poetry'</span><span class="p">,</span> <span class="s">'_vendor'</span><span class="p">)</span>
<span class="n">current_vendors</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span>
<span class="n">vendors</span><span class="p">,</span> <span class="s">'py{}'</span><span class="o">.</span><span class="nb">format</span><span class="p">(</span><span class="s">'.'</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">sys</span><span class="o">.</span><span class="n">version_info</span><span class="p">[:</span><span class="mi">2</span><span class="p">]))</span>
<span class="p">)</span>
<span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">lib</span><span class="p">)</span>
<span class="n">sys</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">current_vendors</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">poetry.core.factory</span> <span class="kn">import</span> <span class="n">Factory</span>
<span class="kn">from</span> <span class="nn">poetry.core.masonry.builders.sdist</span> <span class="kn">import</span> <span class="n">SdistBuilder</span>
<span class="k">except</span> <span class="p">(</span><span class="nb">ImportError</span><span class="p">,</span> <span class="nb">ModuleNotFoundError</span><span class="p">):</span>
<span class="kn">from</span> <span class="nn">poetry.masonry.builders.sdist</span> <span class="kn">import</span> <span class="n">SdistBuilder</span>
<span class="kn">from</span> <span class="nn">poetry.factory</span> <span class="kn">import</span> <span class="n">Factory</span>
<span class="kn">from</span> <span class="nn">poetry.__version__</span> <span class="kn">import</span> <span class="n">__version__</span>
<span class="k">except</span> <span class="p">(</span><span class="nb">ImportError</span><span class="p">,</span> <span class="nb">ModuleNotFoundError</span><span class="p">)</span> <span class="k">as</span> <span class="n">ee</span><span class="p">:</span>
<span class="k">raise</span> <span class="nb">ImportError</span><span class="p">(</span><span class="s">'install poetry by doing pip install poetry to use '</span>
<span class="n">f</span><span class="s">'this script: {ee}'</span><span class="p">)</span>
<span class="c1"># Generate a Poetry object that knows about the metadata in pyproject.toml
</span><span class="n">factory</span> <span class="o">=</span> <span class="n">Factory</span><span class="p">()</span>
<span class="n">poetry</span> <span class="o">=</span> <span class="n">factory</span><span class="o">.</span><span class="n">create_poetry</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">__file__</span><span class="p">))</span>
<span class="c1"># Use the SdistBuilder to genrate a blob for setup.py
</span><span class="k">if</span> <span class="n">StrictVersion</span><span class="p">(</span><span class="n">__version__</span><span class="p">)</span> <span class="o">>=</span> <span class="n">StrictVersion</span><span class="p">(</span><span class="s">'1.1.0b1'</span><span class="p">):</span>
<span class="n">sdist_builder</span> <span class="o">=</span> <span class="n">SdistBuilder</span><span class="p">(</span><span class="n">poetry</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">sdist_builder</span> <span class="o">=</span> <span class="n">SdistBuilder</span><span class="p">(</span><span class="n">poetry</span><span class="p">,</span> <span class="bp">None</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
<span class="n">setuppy_blob</span> <span class="o">=</span> <span class="n">sdist_builder</span><span class="o">.</span><span class="n">build_setup</span><span class="p">()</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'setup.py'</span><span class="p">,</span> <span class="s">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">unit</span><span class="p">:</span>
<span class="n">unit</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">setuppy_blob</span><span class="p">)</span>
<span class="n">unit</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">b</span><span class="s">'</span><span class="se">\n</span><span class="s"># This setup.py was autogenerated using poetry.</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span>
</code></pre></div></div>
<h2 id="challenges">Challenges</h2>
<ul>
<li>I still have issues with pyenv which I need to figure how to <a href="https://github.com/pyenv/pyenv#how-it-works">easily switch between python versions</a></li>
</ul>
<h2 id="references">References</h2>
<ul>
<li><a href="https://python-poetry.org/docs/basic-usage/">Poetry Documentation</a></li>
</ul>Poetry First ImpressionsIntent detection2020-09-20T00:00:00-05:002020-09-20T00:00:00-05:00https://manisnesan.github.io/chrestotes/intent-detection/text-classification/information-retrieval/query-understanding/machine-learning/2020/09/20/intent-detection<!--
#################################################
### THIS FILE WAS AUTOGENERATED! DO NOT EDIT! ###
#################################################
# file to edit: _notebooks/2020-09-20-intent-detection.ipynb
-->
<div class="container" id="notebook-container">
<div class="cell border-box-sizing code_cell rendered">
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Introduction">Introduction<a class="anchor-link" href="#Introduction"> </a></h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Intent Classification is a type of supervised text classification problem. It is used to predict the motivation of the user providing search keywords in a given search engine. Each user visiting the site have a goal in mind and they express in the form of keywords. We have to optimize for satisfying their goal in addition to returning the best documents matching the keywords as search results. In <a href="https://medium.com/@dtunkelang/search-intent-not-inventory-289386f28a21">Search for intent, Not inventory</a>[1] Daniel Tunkelang author of Query Understanding publication emphasizes that</p>
<blockquote><p>"Searchers don’t care what you have in your catalog or how you organize your inventory. They care about what they want. Make it easy for searchers to express their intent, and craft the search experience around their intent."</p>
</blockquote>
<p>Hence as part of Red Hat Customer Portal personalization, we started working on identifying the intents for our site visitor and classify the search queries in order to craft the search experience based on their intent.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Related-Work">Related Work<a class="anchor-link" href="#Related-Work"> </a></h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>Classification of searches is domain specific and there is no one size fits all approach. <strong>Taxonomy of Web Searches</strong>[2] classify the queries into these categories 1. Navigational 2. Informational 3. Transactional</p>
<p><img src="/chrestotes/images/copied_from_nb/images/intent-types.png" alt="" /></p>
<p><strong><a href="https://www.researchgate.net/profile/Parikshit_Sondhi/publication/326133502_A_Taxonomy_of_Queries_for_E-commerce_Search/links/5b78b746a6fdcc5f8b53928f/A-Taxonomy-of-Queries-for-E-commerce-Search.pdf">Taxonomy of Ecommerce Searches</a></strong>[3] classifies them into following categories & each with a distinct search behavior.</p>
<blockquote><ol>
<li><strong>Shallow Exploration</strong> Queries are short vague queries that a user may use initially in exploring the product space. </li>
<li><strong>Targeted Purchase Queries</strong> are queries used by users to purchase items that they are generally familiar with, thus without much decision making. </li>
<li><strong>Major-Item Shopping Queries</strong> are used by users shopping a major item relatively expensive & requires some serious exploration, but typically in a limited scope of choices.</li>
<li><strong>Minor-Item Shopping Queries</strong> are provided by users to shop for minor items that are generally not very expensive, but still require some exploration of choices. </li>
<li><strong>Hard-Choice Shopping Queries</strong> are used by users who want to deeply explore all the candidate products before finalizing the choice often appropriate when multiple products must be carefully compared with each other. </li>
</ol>
</blockquote>
<p>Examples</p>
<p><img src="/chrestotes/images/copied_from_nb/images/ecommerce-search-examples.png" alt="" /></p>
<p><img src="/chrestotes/images/copied_from_nb/images/Illustration-of-Taxonomy-of-E-Com-Queries.png" alt="" /></p>
<p>We looked at how others are handling the intent classification problem because of the shorter length of the text and latency requirement. <a href="https://www.arxiv-vanity.com/papers/2008.06759/">Deep Search Query Intent Understanding</a> from LinkedIn provides two designs for modeling 1. Predicting the intent in typeahead search using character models 2. Predicting the intent for complete search queries to do Seach Results Page(SERP) Blending. Each linkedin usecase has its own latency and accuracy requirement, former having higher latency but with <strong>lower accuracy</strong> whereas the latter with acceptable latency but with <strong>higher accuracy</strong>. Though they explored deep learning CNN, LSTM, BERT models in this paper, production baseline model used is the traditional logistic regression model. Unless you can reduce the size of the model, latency will pose a challenge for productionizing these bigger models.> "The production baseline model is a logistic regression model, with bag-of-words features, and user profile/behavioral features, etc. "</p>
<p><img src="https://d3i71xaburhd42.cloudfront.net/0765baddc2b83166f123f3fddd5557638d8d8f43/2-Figure1-1.png" alt="" />
The next one is <a href="https://medium.com/airbnb-engineering/discovering-and-classifying-in-app-message-intent-at-airbnb-6a55f5400a0c">Discovering and Classifying In-app Message Intent at Airbnb</a> where they classify the guest messaging intents such as Parking, Checking In and try to provide timely responses. Here they found CNN performed better and has faster training with a shorter serving time.</p>
<p><img src="https://miro.medium.com/max/700/0*rAg_GNQYzqNLzCUE" alt="" /></p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Problem-Framing">Problem Framing<a class="anchor-link" href="#Problem-Framing"> </a></h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>We leveraged the redhat customer portal top tasks survey in which most of the users indicated the aspect of problem solving as the main reason for the visit in 4/5 responses. Keeping that in mind, we analyzed the search queries for the patterns and came up with these four buckets.</p>
<ol>
<li>Broad Explorational are single worded vague queries provided by users exploring the product portfolio, a component, vulnerability.</li>
<li>Targeted Queries (Eg: CVE-1243, RHBA-2351, RHSA-3194) such as Bug fixes, Advisories, Enhancements.</li>
<li>Usage Queries are provided by users wanting to know how to use specific component or aspect of a product. </li>
<li>Troubleshoot are provided by users facing an issue and more likely leading to case creation.</li>
</ol>
<p>Instead of providing the model with poor data, we wanted the model to focus only on classifying the Usage and Troublesoot. We avoided passing the models with vague queries and targeted queries and let the keyword search, onebox and curated searches to handle these types of queries.</p>
<table>
<thead><tr>
<th>INTENT</th>
<th>DEFINITION</th>
<th>EXAMPLES</th>
</tr>
</thead>
<tbody>
<tr>
<td>Troublesoot</td>
<td>When a user reports an issue/error message or expresses the text in negative forms explicitly that he/she wants to troubleshoot/debug, then such statements are considered to be of TROUBLESHOOT intent</td>
<td>X Window won't start after updating xorg-x11-server-Xorg package? </td>
</tr>
<tr>
<td></td>
</tr>
<tr>
<td>Usage</td>
<td>USAGE intent is considered when it is more along the lines of how to use a product/component or perform an action.</td>
<td>How can I block video streaming using squid ?</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Data-Collection">Data Collection<a class="anchor-link" href="#Data-Collection"> </a></h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>In order to iterate and perform rapid prototyping, we leverage ML teaching and annotation tool <strong><a href="https://prodi.gy/">Prodigy</a></strong>. The recommendation is to perform manual annotation with <strong>binary label</strong> in order to keep cognitive load low. This allows the annotator to focus only one concept at a time. We started looking at the Portal Search queries and manually annotated them as TROUBLESHOOT or not. Please check this excellent <a href="https://youtu.be/5di0KlKl0fE">text classification tutorial</a> by Ines Montani.</p>
<blockquote><p>If you only provide a single label, the annotation decision becomes much simpler:does the label apply or not? In this case, Prodigy will present the question as a binary task using the classification interface. You can then hit ACCEPT or REJECT. Even if you have more than one label, it can sometimes be very efficient to make several passes over the data instead of selecting from a list of options. The annotators can focus on one concept at a time, which can reduce the potential for human error – especially when working with complicated texts and label schemes.
<code>$ prodigy textcat.teach troubleshoot en_core_web_sm troubleshoot.jsonl</code></p>
</blockquote>
<p>We collected around 1500 training samples to bootstrap the project with the help of Active learning features provided. Learn more about active learning from <a href="https://www.datacamp.com/community/tutorials/active-learning">here</a></p>
<p><strong>Example training samples</strong></p>
<div class="highlight"><pre><span></span><span class="p">{</span><span class="nt">"text"</span><span class="p">:</span><span class="s2">"add new nfs storage"</span><span class="p">,</span><span class="nt">"label"</span><span class="p">:</span><span class="s2">"USAGE"</span><span class="p">,</span><span class="nt">"answer"</span><span class="p">:</span><span class="s2">"accept"</span><span class="p">}</span>
<span class="p">{</span><span class="nt">"text"</span><span class="p">:</span><span class="s2">"sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target"</span><span class="p">,</span><span class="nt">"label"</span><span class="p">:</span><span class="s2">"TROUBLESHOOT"</span><span class="p">,</span><span class="nt">"answer"</span><span class="p">:</span><span class="s2">"accept"</span><span class="p">}</span>
</pre></div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Imports-and-Utilty-functions">Imports and Utilty functions<a class="anchor-link" href="#Imports-and-Utilty-functions"> </a></h2><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">common_word_removal</span><span class="p">(</span><span class="n">df</span><span class="p">,</span> <span class="n">common_words</span><span class="p">):</span>
<span class="sd">"""This is to remove manually identified common words from the training corpus."""</span>
<span class="c1"># Manual list of common words to be removed based on above data. This will change based on text data input.</span>
<span class="c1"># We cannot automate this to directly omit the first x words as these words are very relevant to our use case</span>
<span class="c1"># of inferring intent</span>
<span class="n">df</span><span class="p">[</span><span class="s1">'text'</span><span class="p">]</span> <span class="o">=</span> <span class="n">df</span><span class="p">[</span><span class="s1">'text'</span><span class="p">]</span><span class="o">.</span><span class="n">apply</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="s2">" "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">x</span><span class="o">.</span><span class="n">split</span><span class="p">()</span> <span class="k">if</span> <span class="n">x</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">common_words</span><span class="p">))</span>
<span class="k">return</span> <span class="n">df</span>
<span class="k">def</span> <span class="nf">drop_nulls</span><span class="p">(</span><span class="n">df</span><span class="p">):</span>
<span class="sd">"""This function drops the rows in data with null values. </span>
<span class="sd"> It takes in the raw queries as the input."""</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Number of queries with null values: '</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">df</span><span class="p">[</span><span class="s1">'text'</span><span class="p">]</span><span class="o">.</span><span class="n">isnull</span><span class="p">()</span><span class="o">.</span><span class="n">sum</span><span class="p">()))</span>
<span class="n">df</span><span class="o">.</span><span class="n">dropna</span><span class="p">(</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="k">return</span> <span class="n">df</span>
<span class="k">def</span> <span class="nf">avg_word</span><span class="p">(</span><span class="n">sentence</span><span class="p">):</span>
<span class="sd">"""Used in EDA to calculate average wordlength per query"""</span>
<span class="n">words</span> <span class="o">=</span> <span class="n">sentence</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
<span class="k">return</span> <span class="p">(</span><span class="nb">sum</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">word</span><span class="p">)</span> <span class="k">for</span> <span class="n">word</span> <span class="ow">in</span> <span class="n">words</span><span class="p">)</span><span class="o">/</span><span class="nb">len</span><span class="p">(</span><span class="n">words</span><span class="p">))</span>
</pre></div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Data-Preparation">Data Preparation<a class="anchor-link" href="#Data-Preparation"> </a></h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Loading-the-data-in-dataframe">Loading the data in dataframe<a class="anchor-link" href="#Loading-the-data-in-dataframe"> </a></h3><p>This reads the dataset in json lines format into pandas dataframe.</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">load</span><span class="p">():</span>
<span class="n">raw_data</span> <span class="o">-</span> <span class="n">load_raw_data</span><span class="p">(</span><span class="n">pd</span><span class="o">.</span><span class="n">read_json</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">DATA_DIR</span><span class="si">}</span><span class="s2">/portalsearch/portalsearch.jsonl"</span><span class="p">,</span> <span class="n">lines</span><span class="o">=</span><span class="kc">True</span><span class="p">))</span>
<span class="c1"># Joining the 'label' and 'answer' column to become one. </span>
<span class="c1"># E.g.: Troubleshoot-accept, Troubleshoot-reject, Usage-accept, Usage-reject</span>
<span class="n">raw_data</span><span class="p">[</span><span class="s1">'label'</span><span class="p">]</span> <span class="o">=</span> <span class="n">raw_data</span><span class="p">[</span><span class="s1">'label'</span><span class="p">]</span> <span class="o">+</span> <span class="s1">'-'</span> <span class="o">+</span> <span class="n">raw_data</span><span class="p">[</span><span class="s1">'answer'</span><span class="p">]</span>
<span class="c1"># Only selecting the 'accept' labels.</span>
<span class="n">raw_data</span> <span class="o">=</span> <span class="n">raw_data</span><span class="p">[</span><span class="n">raw_data</span><span class="p">[</span><span class="s1">'label'</span><span class="p">]</span><span class="o">.</span><span class="n">isin</span><span class="p">([</span><span class="s1">'TROUBLESHOOT-accept'</span><span class="p">,</span><span class="s1">'USAGE-accept'</span><span class="p">])]</span>
<span class="n">raw_data</span><span class="o">.</span><span class="n">drop</span><span class="p">(</span><span class="s1">'answer'</span><span class="p">,</span><span class="n">axis</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="k">return</span> <span class="n">raw_data</span>
</pre></div>
<h3 id="Preprocessing">Preprocessing<a class="anchor-link" href="#Preprocessing"> </a></h3><p>We performed the following preprocessing</p>
<ul>
<li>Adding standard features like word count, character count and average word length per query to the dataframe.</li>
<li>Remove captalization by lowercasing all words</li>
<li>Removing punctuations and special characters</li>
<li>Remove traditional stopwords like "the", "a", "an" and "and"</li>
<li>Remove noisy data that are of low value and commonly occuring terms</li>
<li>Lemmatization</li>
</ul>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">eda</span><span class="p">(</span><span class="n">df</span><span class="p">):</span>
<span class="sd">"""Classic EDA like word count per query, average word length per query etc."""</span>
<span class="c1"># Word count per query</span>
<span class="n">df</span><span class="p">[</span><span class="s1">'word_count'</span><span class="p">]</span> <span class="o">=</span> <span class="n">df</span><span class="p">[</span><span class="s1">'text'</span><span class="p">]</span><span class="o">.</span><span class="n">apply</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="nb">len</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">" "</span><span class="p">)))</span>
<span class="c1"># Character count per query</span>
<span class="n">df</span><span class="p">[</span><span class="s1">'character_count'</span><span class="p">]</span> <span class="o">=</span> <span class="n">df</span><span class="p">[</span><span class="s1">'text'</span><span class="p">]</span><span class="o">.</span><span class="n">str</span><span class="o">.</span><span class="n">len</span><span class="p">()</span> <span class="c1"># this also includes spaces</span>
<span class="c1"># Average word length per query</span>
<span class="n">df</span><span class="p">[</span><span class="s1">'avg_wordlength_per_query'</span><span class="p">]</span> <span class="o">=</span> <span class="n">df</span><span class="p">[</span><span class="s1">'text'</span><span class="p">]</span><span class="o">.</span><span class="n">apply</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">avg_word</span><span class="p">(</span><span class="n">x</span><span class="p">))</span>
<span class="k">return</span> <span class="n">df</span>
</pre></div>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">preprocessing</span><span class="p">(</span><span class="n">df</span><span class="p">):</span>
<span class="sd">"""Traditional Pre-processing steps."""</span>
<span class="c1"># Lower case for all words. This helps in removing duplicates later</span>
<span class="n">df</span><span class="p">[</span><span class="s1">'text'</span><span class="p">]</span> <span class="o">=</span> <span class="n">df</span><span class="p">[</span><span class="s1">'text'</span><span class="p">]</span><span class="o">.</span><span class="n">apply</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="s2">" "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">x</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">x</span><span class="o">.</span><span class="n">split</span><span class="p">()))</span>
<span class="c1"># Removing Punctuations and special characters using regular expression</span>
<span class="n">df</span><span class="p">[</span><span class="s1">'text'</span><span class="p">]</span> <span class="o">=</span> <span class="n">df</span><span class="p">[</span><span class="s1">'text'</span><span class="p">]</span><span class="o">.</span><span class="n">str</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'[^\w\s]'</span><span class="p">,</span><span class="s1">''</span><span class="p">)</span>
<span class="c1"># Removing non-english words</span>
<span class="n">df</span><span class="p">[</span><span class="s1">'text'</span><span class="p">]</span> <span class="o">=</span> <span class="n">df</span><span class="p">[</span><span class="s1">'text'</span><span class="p">]</span><span class="o">.</span><span class="n">apply</span><span class="p">(</span><span class="k">lambda</span> <span class="n">row</span><span class="p">:</span> <span class="n">row</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">'ascii'</span><span class="p">,</span><span class="n">errors</span><span class="o">=</span><span class="s1">'ignore'</span><span class="p">)</span><span class="o">.</span><span class="n">decode</span><span class="p">())</span>
<span class="c1"># Removing stopwords</span>
<span class="n">df</span><span class="p">[</span><span class="s1">'text'</span><span class="p">]</span> <span class="o">=</span> <span class="n">df</span><span class="p">[</span><span class="s1">'text'</span><span class="p">]</span><span class="o">.</span><span class="n">apply</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="s2">" "</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">x</span><span class="o">.</span><span class="n">split</span><span class="p">()</span> <span class="k">if</span> <span class="n">x</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">stop</span><span class="p">))</span>
<span class="c1"># Lemmatization</span>
<span class="n">lemmatizer</span> <span class="o">=</span> <span class="n">WordNetLemmatizer</span><span class="p">()</span>
<span class="n">df</span><span class="p">[</span><span class="s1">'text'</span><span class="p">]</span> <span class="o">=</span> <span class="n">df</span><span class="p">[</span><span class="s1">'text'</span><span class="p">]</span><span class="o">.</span><span class="n">apply</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="s2">" "</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="n">lemmatizer</span><span class="o">.</span><span class="n">lemmatize</span><span class="p">(</span><span class="n">word</span><span class="p">)</span> <span class="k">for</span> <span class="n">word</span> <span class="ow">in</span> <span class="n">x</span><span class="o">.</span><span class="n">split</span><span class="p">()]))</span>
<span class="c1"># Common word removal</span>
<span class="c1"># Remove commonly occurring words from our text data </span>
<span class="c1"># as their presence will not of any use in classification of our text data.</span>
<span class="c1"># This step would require manual scanning through the list.</span>
<span class="n">frequent_words</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">Series</span><span class="p">(</span><span class="s1">' '</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">df</span><span class="p">[</span><span class="s1">'text'</span><span class="p">])</span><span class="o">.</span><span class="n">split</span><span class="p">())</span><span class="o">.</span><span class="n">value_counts</span><span class="p">()</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Top 20 frequent words are </span><span class="se">\n</span><span class="s1">'</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">frequent_words</span><span class="p">[:</span><span class="mi">20</span><span class="p">]))</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="p">)</span>
<span class="c1"># Rare words removal</span>
<span class="c1"># Because they’re so rare, the association between them and other words is dominated by noise. </span>
<span class="c1"># Hence we can remove them and later decide whether or not the results improved based on it.</span>
<span class="c1"># Printing out rare words occuring less than 50 times.</span>
<span class="n">rare_words</span> <span class="o">=</span> <span class="n">frequent_words</span><span class="p">[</span><span class="n">frequent_words</span> <span class="o"><</span> <span class="mi">50</span><span class="p">]</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Top 10 rare words are: </span><span class="se">\n</span><span class="s1">'</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">rare_words</span><span class="p">[</span><span class="o">-</span><span class="mi">10</span><span class="p">:]))</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="p">)</span>
<span class="c1"># Dropping queries which are empty after all the pre-processing</span>
<span class="n">df</span><span class="p">[</span><span class="s1">'text'</span><span class="p">]</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">''</span><span class="p">,</span> <span class="n">np</span><span class="o">.</span><span class="n">nan</span><span class="p">,</span> <span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="n">df</span><span class="o">.</span><span class="n">dropna</span><span class="p">(</span><span class="n">inplace</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'The final number of queries after preprocessing are: '</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">df</span><span class="o">.</span><span class="n">shape</span><span class="p">))</span>
<span class="k">return</span> <span class="n">df</span>
</pre></div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Modeling">Modeling<a class="anchor-link" href="#Modeling"> </a></h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Train-Test-Split">Train Test Split<a class="anchor-link" href="#Train-Test-Split"> </a></h3><p>Next we split the data into training and test data with 3:1 split</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">train_test_splits</span><span class="p">(</span><span class="n">df</span><span class="p">,</span> <span class="n">test_size</span><span class="p">):</span>
<span class="sd">"""Splitting raw data into training and test data."""</span>
<span class="n">X</span> <span class="o">=</span> <span class="n">raw_data</span><span class="p">[</span><span class="s1">'text'</span><span class="p">]</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">raw_data</span><span class="p">[</span><span class="s1">'label'</span><span class="p">]</span>
<span class="n">X_train</span><span class="p">,</span> <span class="n">X_test</span><span class="p">,</span> <span class="n">y_train</span><span class="p">,</span> <span class="n">y_test</span> <span class="o">=</span> <span class="n">train_test_split</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">test_size</span><span class="o">=</span><span class="n">test_size</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">42</span><span class="p">)</span>
<span class="k">return</span> <span class="n">X_train</span><span class="p">,</span> <span class="n">X_test</span><span class="p">,</span> <span class="n">y_train</span><span class="p">,</span> <span class="n">y_test</span>
</pre></div>
<div class="highlight"><pre><span></span><span class="c1"># Splitting raw dataset into testing and training data</span>
<span class="n">X_train</span><span class="p">,</span> <span class="n">X_test</span><span class="p">,</span> <span class="n">y_train</span><span class="p">,</span> <span class="n">y_test</span> <span class="o">=</span> <span class="n">train_test_splits</span><span class="p">(</span><span class="n">raw_data</span><span class="p">,</span><span class="mf">0.33</span><span class="p">)</span>
</pre></div>
<h3 id="Vectorization">Vectorization<a class="anchor-link" href="#Vectorization"> </a></h3><p>The text needs to be converted into a format that a model could interpret ie numbers. This process is called vectorization. We started with Term Frequency-Inverse Document Frequency(TF-IDF) method using sklearn <code>TfidfVectorizer</code></p>
<blockquote><p>TF-IDF is a way to calculate the ‘importance’ of each word in the dataset. This vectorizer calculates how often a given word appears in the string, and downscales words that appear across different strings.</p>
</blockquote>
<p>An example illustrating how tfidf is calculate for two strings</p>
<p><img src="/chrestotes/images/copied_from_nb/images/tf-idf-example.png" alt="" /></p>
<p>Code sample</p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">text_vectorization_tfidf</span><span class="p">(</span><span class="n">X_train</span><span class="p">,</span><span class="n">X_test</span><span class="p">):</span><span class="s2">"""tf-idf vectorization using sklearn"""</span>
<span class="n">vectorizer</span> <span class="o">=</span> <span class="n">TfidfVectorizer</span><span class="p">()</span>
<span class="n">X_train_vec</span> <span class="o">=</span> <span class="n">vectorizer</span><span class="o">.</span><span class="n">fit_transform</span><span class="p">(</span><span class="n">X_train</span><span class="p">)</span>
<span class="n">X_test_vec</span> <span class="o">=</span> <span class="n">vectorizer</span><span class="o">.</span><span class="n">transform</span><span class="p">(</span><span class="n">X_test</span><span class="p">)</span>
<span class="c1"># pretty printing the vocabulary built by the tf-idf vectorizer</span>
<span class="c1"># pprint.pprint(vectorizer.vocabulary_)</span>
<span class="k">return</span> <span class="n">vectorizer</span><span class="p">,</span> <span class="n">X_train_vec</span><span class="p">,</span> <span class="n">X_test_vec</span>
<span class="c1"># Text Vectorization of training data</span>
<span class="n">vectorizer</span><span class="p">,</span> <span class="n">X_train_vec</span><span class="p">,</span> <span class="n">X_test_vec</span> <span class="o">=</span> <span class="n">text_vectorization_tfidf</span><span class="p">(</span><span class="n">X_train</span><span class="p">,</span> <span class="n">X_test</span><span class="p">)</span>
</pre></div>
<h3 id="LinearSVC">LinearSVC<a class="anchor-link" href="#LinearSVC"> </a></h3><blockquote><p>The algorithm we used is a linear support vector classifier (SVC), a commonly used text classification algorithm that works by finding the line or hyper-plane that best differentiates two groups of data points. It is a Support Vector Machine with a linear kernel.Learn more about SVM from <a href="https://www.datacamp.com/community/tutorials/svm-classification-scikit-learn-python">here</a>
Here we are performing 3-fold cross validation to improve the generalization and minimize the overfitting on validation set. With the given training set, it is split into 3 folds and one of the fold is used for validation and a score is calculated. Similarity this process repeated with the rest of the folds and the average of all the scores is used as the final score. Please see the excellent scikit guide <a href="https://scikit-learn.org/stable/modules/cross_validation.html#cross-validation">here</a> for additional details</p>
</blockquote>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">build_model</span><span class="p">(</span><span class="n">X_train_vec</span><span class="p">,</span> <span class="n">y_train</span><span class="p">):</span>
<span class="sd">"""Build an SVM model with a linear kernel"""</span>
<span class="n">svm</span> <span class="o">=</span> <span class="n">LinearSVC</span><span class="p">(</span><span class="n">class_weight</span><span class="o">=</span><span class="s2">"balanced"</span><span class="p">)</span>
<span class="n">linear_svc</span> <span class="o">=</span> <span class="n">CalibratedClassifierCV</span><span class="p">(</span><span class="n">svm</span><span class="p">,</span><span class="n">method</span><span class="o">=</span><span class="s1">'sigmoid'</span><span class="p">)</span>
<span class="c1"># 3-fold Cross-Validation</span>
<span class="nb">print</span><span class="p">(</span><span class="n">cross_val_score</span><span class="p">(</span><span class="n">linear_svc</span><span class="p">,</span> <span class="n">X_train_vec</span><span class="p">,</span> <span class="n">y_train</span><span class="p">,</span> <span class="n">cv</span><span class="o">=</span><span class="mi">3</span><span class="p">))</span>
<span class="c1"># Fitting the model after tuning parameters based on cross-validation results</span>
<span class="n">linear_svc</span><span class="o">.</span><span class="n">fit</span><span class="p">(</span><span class="n">X_train_vec</span><span class="p">,</span> <span class="n">y_train</span><span class="p">)</span>
<span class="k">return</span> <span class="n">linear_svc</span>
<span class="c1"># Building, cross validation and fitting of model</span>
<span class="n">model</span> <span class="o">=</span> <span class="n">build_model</span><span class="p">(</span><span class="n">X_train_vec</span><span class="p">,</span> <span class="n">y_train</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Evaluation">Evaluation<a class="anchor-link" href="#Evaluation"> </a></h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>The model can be interpreted by looking at the confusion matrix of true labels and predicted labels. Confusion matrix(a.k.a error matrix) allows to understand the performance of the model on unseen or test queries. We can see the accuracy of the model to be around <strong>95%</strong></p>
<div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">make_predictions</span><span class="p">(</span><span class="n">model</span><span class="p">,</span><span class="n">X_test_vec</span><span class="p">):</span>
<span class="sd">"""Makes predictions and spits out confusion matrix."""</span>
<span class="c1"># Predicting results on test data</span>
<span class="n">predictions</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">predict</span><span class="p">(</span><span class="n">X_test_vec</span><span class="p">)</span>
<span class="c1"># Accuracy of model</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Accuracy of model is '</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="n">accuracy_score</span><span class="p">(</span><span class="n">y_test</span><span class="p">,</span> <span class="n">predictions</span><span class="p">)</span><span class="o">*</span><span class="mi">100</span><span class="p">,</span><span class="mi">2</span><span class="p">))</span> <span class="o">+</span> <span class="s1">'%'</span><span class="p">)</span>
<span class="c1"># Precision, Recall and other metrics</span>
<span class="nb">print</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">classification_report</span><span class="p">(</span><span class="n">y_test</span><span class="p">,</span> <span class="n">predictions</span><span class="p">,</span> <span class="n">target_names</span><span class="o">=</span><span class="p">[</span><span class="s1">'TROUBLESHOOT-accept'</span><span class="p">,</span> <span class="s1">'USAGE-accept'</span><span class="p">])))</span>
<span class="c1"># Confusion Matrix</span>
<span class="n">labels</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'TROUBLESHOOT-accept'</span><span class="p">,</span><span class="s1">'USAGE-accept'</span><span class="p">]</span>
<span class="n">Confusion_Matrix</span> <span class="o">=</span> <span class="n">confusion_matrix</span><span class="p">(</span><span class="n">y_test</span><span class="p">,</span> <span class="n">predictions</span><span class="p">,</span> <span class="n">labels</span><span class="p">)</span>
<span class="c1"># Plotting the confusion matrix</span>
<span class="n">df_cm</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">(</span><span class="n">Confusion_Matrix</span><span class="p">,</span> <span class="n">index</span> <span class="o">=</span> <span class="n">labels</span><span class="p">,</span>
<span class="n">columns</span> <span class="o">=</span> <span class="n">labels</span><span class="p">)</span>
<span class="n">ax</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">(</span><span class="n">figsize</span> <span class="o">=</span> <span class="p">(</span><span class="mi">12</span><span class="p">,</span><span class="mi">8</span><span class="p">))</span>
<span class="n">sns</span><span class="o">.</span><span class="n">heatmap</span><span class="p">(</span><span class="n">df_cm</span><span class="p">,</span> <span class="n">annot</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span><span class="n">fmt</span><span class="o">=</span><span class="s1">'g'</span><span class="p">)</span>
<span class="c1"># labels, title and ticks</span>
<span class="n">ax</span><span class="o">.</span><span class="n">suptitle</span><span class="p">(</span><span class="s1">'Confusion Matrix'</span><span class="p">)</span>
<span class="n">plt</span><span class="o">.</span><span class="n">xlabel</span><span class="p">(</span><span class="s1">'Predicted labels'</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">18</span><span class="p">)</span>
<span class="n">plt</span><span class="o">.</span><span class="n">ylabel</span><span class="p">(</span><span class="s1">'True labels'</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">16</span><span class="p">)</span>
</pre></div>
<p><img src="/chrestotes/images/copied_from_nb/images/confusion-matrix.png" alt="" /></p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Deployment">Deployment<a class="anchor-link" href="#Deployment"> </a></h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Web-application">Web application<a class="anchor-link" href="#Web-application"> </a></h3><p>Once the model is trained and saved, the next step is to create a simple REST endpoint called introspect where the client applications can send the text blob and get the intent prediction as the response. The application endpoint is built using python, flask web framework, gunicorn web containier with 4 parallel workers. The overview of the application is as follows</p>
<ul>
<li>Loading the model at the application startup </li>
<li>Once the query is received, send it to the model only if it is <strong>not</strong> a known lexical pattern like CVE, Errata, numeric id, url. This prevents garbage inputs and invalid predictions. </li>
<li>If the query is one of the known patten return the response with the intent as OTHER.</li>
<li>Transform the query into a vectorized form before model prediction</li>
<li>Predict the query and return the prediction, probablity of the predicted class as confidence score. </li>
</ul>
<h3 id="Containerizing-the-application">Containerizing the application<a class="anchor-link" href="#Containerizing-the-application"> </a></h3><p>Basically <a href="https://hackernoon.com/what-is-containerization-83ae53a709a6">containeraization</a> is a modern way to package the application with your code, dependencies, configuration into a format (Eg: Docker Image) suitable to run anywhere whether it's public cloud like aws or in your own datacenter.</p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p><strong>Code Sample for util.py</strong></p>
<div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">request</span><span class="p">,</span> <span class="n">Response</span>
<span class="kn">from</span> <span class="nn">validators</span> <span class="kn">import</span> <span class="n">ValidationFailure</span>
<span class="kn">from</span> <span class="nn">validators.url</span> <span class="kn">import</span> <span class="n">url</span>
<span class="kn">from</span> <span class="nn">functools</span> <span class="kn">import</span> <span class="n">wraps</span>
<span class="kn">import</span> <span class="nn">logging</span>
<span class="k">def</span> <span class="nf">is_url</span><span class="p">(</span><span class="n">keyword</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="nb">bool</span><span class="p">:</span>
<span class="sd">'''</span>
<span class="sd"> Returns True if the keyword contains a valid url else return False</span>
<span class="sd"> '''</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">value</span> <span class="o">=</span> <span class="n">url</span><span class="p">(</span><span class="n">keyword</span><span class="p">)</span>
<span class="k">except</span> <span class="n">ValidationFailure</span><span class="p">:</span>
<span class="k">return</span> <span class="kc">False</span>
<span class="k">return</span> <span class="n">value</span>
<span class="k">def</span> <span class="nf">has_known_lexical_pattern</span><span class="p">(</span><span class="n">keyword</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="nb">bool</span><span class="p">:</span>
<span class="sd">'''</span>
<span class="sd"> Return True if the keyword contains known navigational intent like CVE, Errata, id or url else</span>
<span class="sd"> returns False</span>
<span class="sd"> '''</span>
<span class="c1">#Navigational intent for CVE, Errata, id or url</span>
<span class="k">return</span> <span class="n">keyword</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">.</span><span class="n">startswith</span><span class="p">((</span><span class="s1">'cve'</span><span class="p">,</span> <span class="s1">'(cve'</span><span class="p">,</span> <span class="s1">'rhsa'</span><span class="p">,</span> <span class="s1">'(rhsa'</span><span class="p">,</span> <span class="s1">'rhba'</span><span class="p">,</span> <span class="s1">'(rhba'</span><span class="p">))</span> <span class="ow">or</span> <span class="n">keyword</span><span class="o">.</span><span class="n">isdigit</span><span class="p">()</span> <span class="ow">or</span> <span class="n">is_url</span><span class="p">(</span><span class="n">keyword</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">has_other_intent</span><span class="p">(</span><span class="n">query</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="nb">bool</span><span class="p">:</span>
<span class="k">return</span> <span class="n">has_known_lexical_pattern</span><span class="p">(</span><span class="n">query</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">invalid_input</span><span class="p">():</span>
<span class="sd">"""Sends a 400 Bad Request"""</span>
<span class="k">return</span> <span class="n">Response</span><span class="p">(</span>
<span class="s1">'ensure this value has at mininum 3 characters and most 500 characters'</span><span class="p">,</span> <span class="mi">400</span><span class="p">,</span>
<span class="p">{})</span>
<span class="k">def</span> <span class="nf">validate_input</span> <span class="p">(</span><span class="n">f</span><span class="p">):</span>
<span class="nd">@wraps</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">decorated</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">query</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">args</span> <span class="p">[</span><span class="s1">'query'</span><span class="p">]</span>
<span class="k">if</span> <span class="nb">len</span> <span class="p">(</span><span class="n">query</span><span class="p">)</span> <span class="o"><</span> <span class="mi">3</span> <span class="ow">or</span> <span class="nb">len</span> <span class="p">(</span><span class="n">query</span><span class="p">)</span> <span class="o">></span> <span class="mi">500</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">Exception</span> <span class="p">()</span>
<span class="k">return</span> <span class="n">f</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">logging</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">"Input validation failed"</span><span class="p">)</span>
<span class="k">return</span> <span class="n">invalid_input</span> <span class="p">()</span>
<span class="k">return</span> <span class="n">decorated</span>
</pre></div>
<p><strong>Code Sample for predict.py Intent Prediction</strong></p>
<div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">Flask</span><span class="p">,</span> <span class="n">jsonify</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="n">Response</span>
<span class="kn">from</span> <span class="nn">functools</span> <span class="kn">import</span> <span class="n">wraps</span>
<span class="kn">from</span> <span class="nn">util</span> <span class="kn">import</span> <span class="n">validate_input</span><span class="p">,</span> <span class="n">has_other_intent</span>
<span class="kn">import</span> <span class="nn">json</span><span class="o">,</span> <span class="nn">pickle</span><span class="o">,</span> <span class="nn">datetime</span><span class="o">,</span> <span class="nn">logging</span><span class="o">,</span> <span class="nn">uuid</span>
<span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Dict</span>
<span class="n">application</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="vm">__name__</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">load_model</span><span class="p">()</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
<span class="sd">'''</span>
<span class="sd"> Initialize the global variables to load the model.</span>
<span class="sd"> '''</span>
<span class="k">global</span> <span class="n">vectorizer</span><span class="p">,</span> <span class="n">model</span>
<span class="n">vectorizer</span> <span class="o">=</span> <span class="n">pickle</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="s2">"./models/tfidf_vectorizer.pkl"</span><span class="p">,</span> <span class="s2">"rb"</span><span class="p">))</span>
<span class="n">model</span> <span class="o">=</span> <span class="n">pickle</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="s2">"./models/intent_clf.pkl"</span><span class="p">,</span> <span class="s2">"rb"</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">initialize</span> <span class="p">():</span>
<span class="n">load_model</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">strip_accept_label</span><span class="p">(</span><span class="n">prediction</span><span class="p">:</span><span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="nb">str</span><span class="p">:</span>
<span class="k">if</span> <span class="s1">'-'</span> <span class="ow">in</span> <span class="n">prediction</span><span class="p">:</span>
<span class="k">return</span> <span class="n">prediction</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'-'</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">return</span> <span class="n">prediction</span>
<span class="nd">@application</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s2">"/introspect"</span><span class="p">,</span> <span class="n">methods</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"GET"</span><span class="p">])</span>
<span class="nd">@validate_input</span>
<span class="k">def</span> <span class="nf">introspect</span><span class="p">()</span> <span class="o">-></span> <span class="n">Dict</span><span class="p">:</span>
<span class="sd">"""</span>
<span class="sd"> Intent Prediction</span>
<span class="sd"> """</span>
<span class="n">query</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">args</span> <span class="p">[</span><span class="s1">'query'</span><span class="p">]</span>
<span class="c1"># Return intent as OTHER for CVE, Errata (RHBA, RHSA), id or url</span>
<span class="k">if</span> <span class="n">has_other_intent</span><span class="p">(</span><span class="n">query</span><span class="p">):</span>
<span class="n">response</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"query"</span><span class="p">:</span> <span class="n">query</span><span class="p">,</span> <span class="s2">"intent"</span><span class="p">:</span> <span class="s1">'OTHER'</span><span class="p">,</span> <span class="s2">"confidence_score"</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="s2">"req_id"</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">uuid</span><span class="o">.</span><span class="n">uuid4</span><span class="p">())}</span>
<span class="n">logging</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Prediction response : </span><span class="si">{</span><span class="n">response</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
<span class="k">return</span> <span class="n">response</span>
<span class="n">query_transformed</span> <span class="o">=</span> <span class="n">vectorizer</span><span class="o">.</span><span class="n">transform</span><span class="p">([</span><span class="n">query</span><span class="p">])</span>
<span class="n">prediction</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">predict</span><span class="p">([</span><span class="n">query_transformed</span><span class="o">.</span><span class="n">toarray</span><span class="p">()[</span><span class="mi">0</span><span class="p">]])[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">prob</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">predict_proba</span><span class="p">([</span><span class="n">query_transformed</span><span class="o">.</span><span class="n">toarray</span><span class="p">()[</span><span class="mi">0</span><span class="p">]])[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">confidence_score</span> <span class="o">=</span> <span class="nb">round</span><span class="p">(</span><span class="nb">max</span><span class="p">(</span><span class="n">prob</span><span class="p">),</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">response</span> <span class="o">=</span> <span class="p">{</span><span class="s2">"query"</span><span class="p">:</span> <span class="n">query</span><span class="p">,</span> <span class="s2">"intent"</span><span class="p">:</span> <span class="n">strip_accept_label</span><span class="p">(</span><span class="n">prediction</span><span class="p">),</span> <span class="s2">"confidence_score"</span><span class="p">:</span> <span class="n">confidence_score</span><span class="p">,</span>
<span class="s2">"req_id"</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">uuid</span><span class="o">.</span><span class="n">uuid4</span><span class="p">())}</span>
<span class="k">return</span> <span class="n">response</span>
<span class="n">initialize</span><span class="p">()</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">"__main__"</span><span class="p">:</span>
<span class="n">initialize</span><span class="p">()</span>
<span class="n">application</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">debug</span> <span class="o">=</span> <span class="kc">True</span><span class="p">,</span> <span class="n">host</span> <span class="o">=</span> <span class="s2">"0.0.0.0"</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="s2">"8080"</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p><strong>Dockerfile sample</strong></p>
<pre><code>FROM registry.access.redhat.com/rhscl/python-36-rhel7
USER root
ADD . /opt/customer-portal-search-intent/
WORKDIR /opt/customer-portal-search-intent
RUN wget http://gss-rdu-repo.usersys.redhat.com/repo/config/intent-detection/intent_clf-version1.pkl \
&& wget http://gss-rdu-repo.usersys.redhat.com/repo/config/intent-detection/intent_clf.pkl \
&& wget http://gss-rdu-repo.usersys.redhat.com/repo/config/intent-detection/tfidf_vectorizer-version1.pkl \
&& wget http://gss-rdu-repo.usersys.redhat.com/repo/config/intent-detection/tfidf_vectorizer.pkl \
&& mv *.pkl models/ \
&& pip install -r requirements.txt
USER 1001
EXPOSE 8080 8443
ENTRYPOINT ["./run_intent_detection_service"]
CMD [ ]</code></pre>
<p><strong>run_intent_detection_service</strong></p>
<pre><code>#!/bin/bash
# Lay down the cert for this server
KEYFILE=cert/rsa.key
CERTFILE=cert/ssl.crt
BIND="127.0.0.1:8080"
if [ -f $KEYFILE ] && [ -f $CERTFILE ] ; then
OPTS="--keyfile $KEYFILE --certfile $CERTFILE $OPTS"
BIND="0.0.0.0:8443"
fi
# num_workers = (2 * cpu) + 1 => 9
OPTS="$OPTS -b $BIND --workers 5 --log-level=DEBUG "
export REQUESTS_CA_BUNDLE=$(pwd)/root.crt
set -x
gunicorn main:application $OPTS --access-logfile - --access-logformat "{'remote_ip':'%(h)s','request_id':'%({X-Request-Id}i)s','response_code':'%(s)s','request_method':'%(m)s','request_path':'%(U)s','request_querystring':'%(q)s','request_timetaken':'%(D)s','response_length':'%(B)s'}"</code></pre>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Building-Image-and-Deployment-on-OpenShift">Building Image and Deployment on OpenShift<a class="anchor-link" href="#Building-Image-and-Deployment-on-OpenShift"> </a></h3>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>In order to make the service available to our users we are going to lean on <a href="https://www.openshift.com/learn/what-is-openshift">OpenShift</a>, container platform for <a href="https://docs.openshift.com/online/starter/welcome/index.html">building the image and deployment</a>.</p>
<p>Once we have trained our model and have the application packaged in a Dockerfile, all we need to provide is BuildTemplate and DeploymentTemplate.</p>
<p>BuildTemplate provides information such as source repository where the Dockerfile(assumed to be at the root), what buildstrategy to use(in this docker strategy) and finally about the ImageRepository for storing the built images.</p>
<p>DeploymentTemplate contains info about cpu, memory requirements on the deployments, number of pods(instances of the services) for availablility and seamlessly transition between the instances during deployment rollouts without service interruption.
<img src="/chrestotes/images/copied_from_nb/images/openshift-build-deploy.png" alt="" /></p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Integration">Integration<a class="anchor-link" href="#Integration"> </a></h2><p>Let's see how this model is integrated with the overall product ecosystem.As a first step in using the service, we wanted to avoid any risks and carefully provide the options to the user to choose troubleshoot experience when we detect the same intent from the query.</p>
<p>In the below example user searching for kernel panic occuring in Red Hat Linux systems, the service predicted the TROUBLESHOOT with greater 70% confidence and a banner showing option to user allowing them to choose TROUBLESHOOT experience.</p>
<p><img src="/chrestotes/images/copied_from_nb/images/intent-customer-portal.png" alt="Red Hat Customer Portal Search Integration" /></p>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="Conclusion">Conclusion<a class="anchor-link" href="#Conclusion"> </a></h2><ul>
<li>In this post, we covered how we went from ideation, data collection, module building, deployment and finally integrating with the product.</li>
<li>There are constraints such as shorter text, latency, model size in choosing a modeling technique for intent classification and creating a simpler & traditional model such as LinearSVC can always be a better fit for such scenarios.</li>
</ul>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h2 id="References">References<a class="anchor-link" href="#References"> </a></h2>
</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<ol>
<li><a href="https://medium.com/@dtunkelang/search-intent-not-inventory-289386f28a21">Search: Intent, Not Inventory</a></li>
<li><a href="https://www.researchgate.net/publication/220466848_A_Taxonomy_of_Web_Search">Broder, Andrei. (2002). A Taxonomy of Web Search. SIGIR Forum. 36. 3-10. 10.1145/792550.792552</a></li>
<li><a href="https://www.researchgate.net/publication/326133502_A_Taxonomy_of_Queries_for_E-commerce_Search">Sondhi, Parikshit & Sharma, Mohit & Kolari, Pranam & Zhai, ChengXiang. (2018). A Taxonomy of Queries for E-commerce Search. 1245-1248. 10.1145/3209978.3210152</a></li>
<li><a href="https://www.arxiv-vanity.com/papers/2008.06759/">Deep Search Query Intent Understanding</a></li>
<li><a href="https://medium.com/airbnb-engineering/discovering-and-classifying-in-app-message-intent-at-airbnb-6a55f5400a0c">Discovering and Classifying In-app Message Intent at Airbnb</a></li>
<li><a href="https://prodi.gy/">Prodigy - ML teaching and annotation tool</a></li>
<li><a href="https://www.datacamp.com/community/tutorials/svm-classification-scikit-learn-python">SVM</a></li>
<li><a href="https://www.datacamp.com/community/tutorials/active-learning">Active Learning</a></li>
<li><a href="https://docs.openshift.com/container-platform/4.3/builds/understanding-image-builds.html">OpenShift Builds</a>
10.<a href="https://docs.openshift.com/container-platform/4.3/applications/deployments/what-deployments-are.html">OpenShift Deployments</a></li>
</ol>
</div>
</div>
</div>
</div>Tracking Data and Model in Machine Learning projects2020-06-29T00:00:00-05:002020-06-29T00:00:00-05:00https://manisnesan.github.io/chrestotes/machine-learning/2020/06/29/tracking-data-model-using-dvc<h2 id="why-should-you-track-everything">Why should you track everything</h2>
<ul>
<li>Difference between software engineering and machine learning projects</li>
<li>code, config, dependencies vs code, data, model, config, dependencies</li>
<li>Myriad of Data files (raw, intermediate)</li>
<li>Not in repository</li>
<li>Reproducible ML models targeting metrics [Experiments Link]</li>
<li>Tuning and Experimentation tracking</li>
<li>Model Deployment & Revert</li>
</ul>
<h2 id="dvc">DVC</h2>
<ul>
<li>
<p>DVC is built to make ML models shareable and reproducible. It is designed to handle large files, data sets, machine learning models, and metrics as well as code.</p>
</li>
<li>Experiments are tracked by combining the Code + Data files</li>
<li>Data files
<ul>
<li>Local cache</li>
<li>Data remotes in S3, SSH etc</li>
</ul>
</li>
<li>Metrics per experiment</li>
<li>Pipelines</li>
</ul>
<h3 id="install-dvc-on-fedorarhelcentos">Install DVC on Fedora/RHEL/CentOS</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>wget https://dvc.org/rpm/dvc.repo <span class="nt">-O</span> /etc/yum.repos.d/dvc.repo
<span class="nb">sudo </span>yum update
<span class="nb">sudo </span>yum <span class="nb">install </span>dvc
</code></pre></div></div>
<p>Add DVC files in the Git (It is not required but it is good to have project and dvc config in the same directory)</p>
<h2 id="workflow-for-model-packaging">Workflow for Model Packaging</h2>
<ul>
<li>Setup for connecting to model repository during training development process</li>
<li>Push the trained model to the repository</li>
<li>Pull the model from the repository during the build process</li>
</ul>
<h3 id="pushing-model-files">Pushing model files</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dvc init
dvc remote add <span class="nt">-d</span> gss-rdu-remote ssh://msivanes@gss-rdu-repo.usersys.redhat.com:/var/www/html/repo/config/ulmfit
dvc add cases_small_sbr_08-06-2020.pkl
git commit <span class="nt">-am</span> “Add ulmfit model to project”
dvc push <span class="nt">-v</span>
</code></pre></div></div>
<h3 id="pulling-the-model">Pulling the model</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone <span class="nv">$REPO</span>
git pull
dvc pull <span class="c"># Pulls the data from remote-storage. Equivalent to dvc fetch followed by dvc checkout</span>
dvc checkout <span class="c">#Update model files</span>
</code></pre></div></div>
<h2 id="food-for-thought">Food for thought</h2>
<ul>
<li>Rather than feature branches, think in terms of experiment branches targeting metrics.</li>
<li>Keep Data and Model files stored outside the repository</li>
<li>Model files built as part of build process.</li>
<li>Smoke test should validate the constructed model using validation set.</li>
</ul>
<h2 id="references">References</h2>
<ul>
<li><a href="https://dvc.org/doc">DVC</a></li>
<li><a href="https://www.globalsqa.com/dvc-cheat-sheet/">Cheatsheet</a></li>
<li>https://christophergs.github.io/machine%20learning/2019/05/13/first-impressions-of-dvc/</li>
<li>https://www.slideshare.net/DmitryPetrov15/pydata-berlin-2018-dvcorg</li>
</ul>Why should you track everythingPaper Summary - Rapidly Deploying a Neural Search Engine for the COVID-19 Open Research Dataset2020-05-25T00:00:00-05:002020-05-25T00:00:00-05:00https://manisnesan.github.io/chrestotes/information-retrieval/deep-learning/papers/2020/05/25/Paper_Summary_Covidex<h1 id="paper-summary---rapidly-deploying-a-neural-search-engine-for-the-covid-19-open-research-dataset">Paper Summary - Rapidly Deploying a Neural Search Engine for the COVID-19 Open Research Dataset</h1>
<h2 id="overview-of-covidexai">Overview of covidex.ai</h2>
<p>This is a paper summary of deploying a Neural Search Engine to answer questions from the COVID-19 dataset.</p>
<ul>
<li><a href="https://openreview.net/pdf?id=PlUA_mgGaPq">Paper</a></li>
<li><a href="http://covidex.ai">covidex.ai</a></li>
<li><a href="https://twitter.com/lintool/status/1248668833713467392?s=20">Twitter Announcement by Jimmy Lin</a></li>
</ul>
<blockquote>
<p>Neural Covidex applies state-of-the-art neural network models and artificial intelligence (AI) techniques to answer questions using the COVID-19 Open Research Dataset (CORD-19) provided by the Allen Institute for AI (data release of April 3, 2020).
This project is led by Jimmy Lin from the University of Waterloo and Kyunghyun Cho from NYU, with a small team of wonderful students: Edwin Zhang and Nikhil Gupta. Special thanks to Colin Raffel for his help in pretraining T5 models for the biomedical domain.”</p>
</blockquote>
<p><img src="https://forums.fast.ai/uploads/default/original/3X/2/2/22fbefd8abb7063ab24722cdda185c523abba6ec.png" alt="alt text" /></p>
<h2 id="motivation">Motivation</h2>
<p>The ongoing pandemic crisis poses a huge challenge to get timely information for public health officials, clinicians, researchers, virologists. In order to respond to this challenge, Allen AI publishes a COVID-19 data set (CORD-19) in collaboration with other research groups. The source for this data set is both research articles published about coronovirus and other related research articles.
The aim of this effort is to bring researchers</p>
<ul>
<li>to apply language processing techniques in order to generate insights & make data driven decisions.</li>
<li>to provide ways for the front line to consume the recent developments in a digestible form & apply in the field.</li>
</ul>
<h2 id="outcomes">Outcomes</h2>
<p>Jimmy Lin & his research team responded to this call. The two strategies adopted were</p>
<ul>
<li>Real time users should be able to find answers to any questions associated with COVID</li>
<li>Other Researchers should be able reuse the components they build. Providing a modular and reusable components is set as part of the requirements.</li>
</ul>
<p>The team decided to build end to end real time search application called covidex.ai . They developed the components that powers this engine in a short span of time for the information retrieval need .</p>
<ul>
<li><strong>keyword based search interface :</strong> This also provides <strong>faceted navigation</strong> in the form of filters like author, article source, time range and <strong>highlighting</strong> words from the results that matches with user query.</li>
<li><strong>neural ranking component</strong> that sorts the results with the top most results answering user’s question.</li>
</ul>
<h2 id="background--related-work">Background & Related Work</h2>
<p>Traditional search architecture comprises of two phases Content Indexing and Keyword Searching. During indexing, content is transformed into an Indexable form called as Document The search engine convert this document into a fundamental data structure called as Inverted Index. This is similar to what you see in Book Appendix where terms are mapped towards the pages. Similarly Inverted index contains terms mapped towards docIds where the term appears & position in the document.</p>
<p>Searching phase is further divided into two stages <strong>retrieval stage</strong> and <strong>ranking stage</strong>. In the first stage, given a search term(s) you will retrieve the list of matching documents from the inverted index. In the second stage, the matched documents are sorted based on the computed relevance score.</p>
<p><strong>Modern</strong> <strong>Search Architectures</strong></p>
<p>More modern multi-stage search architectures from Bing & Alibaba expand the Search Phase with additional reranking stages. Except for the first retrieval stage, the additional subsequent ranking stages will rerank and refine the results further from previous stages .</p>
<h2 id="modular-and-reusable-keyword-search">Modular and Reusable Keyword Search</h2>
<h3 id="anserini">Anserini</h3>
<p>Anserini is an opensource Information Retrieval toolkit in order to solve the reproducibility problems in research and bridge the gap between research and real world systems. This is a tool that is built on top of Lucene, a popular open source search library & enhanced with features specific for conducting IR research. <strong>pyserini</strong> is a python interface to Anserini.</p>
<h3 id="indexing">Indexing</h3>
<p>The first challenge faced by the team is representing the <strong>Indexable Document.</strong> This is fundamental unit of search engine. Results are basically collection of documents. Eg: Tweets, WebPage, Article</p>
<p>One of the common challenge wrt Information Retrieval systems, they tend to favor longer documents. In order to give all documents a fairer chances irrespective of its length, normalization is needed.</p>
<p>The articles are in the following format</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="err">title</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="err">“Impact</span><span class="w"> </span><span class="err">of</span><span class="w"> </span><span class="err">Masks”</span><span class="p">,</span><span class="w">
</span><span class="err">abstract:</span><span class="w"> </span><span class="err">“Masks</span><span class="w"> </span><span class="err">protects</span><span class="w"> </span><span class="err">others</span><span class="w"> </span><span class="err">from</span><span class="w"> </span><span class="err">you.”</span><span class="w">
</span><span class="err">body_text</span><span class="w"> </span><span class="err">:</span><span class="w"> </span><span class="err">“Effectiveness</span><span class="w"> </span><span class="err">of</span><span class="w"> </span><span class="err">mask</span><span class="w"> </span><span class="err">/n</span><span class="w"> </span><span class="err">/n</span><span class="w"> </span><span class="err">This</span><span class="w"> </span><span class="err">is</span><span class="w"> </span><span class="err">being</span><span class="w"> </span><span class="err">studied</span><span class="w"> </span><span class="err">…..”</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>In order to compare the effectiveness, the team decide to index the articles in 3 different ways</p>
<ul>
<li>Index only the title and abstract of the article as a document</li>
<li>Index the entire text of the article as a document combining title, abstract and body_text</li>
<li>Break the body_text of the article into paragraphs and each paragraph as separate documents. In this case, the Indexable Document is title, abstract & the paragraph.</li>
</ul>
<h3 id="searching">Searching</h3>
<p>Once the team built the lucene indices based on the above scheme for CORD-19, we can able to search for a given term, retrieve matching documents and ranked them using BM25 scoring function. These indices are available for the researchers to perform further research.</p>
<p>The full search pipeline for keyword search is demonstrated using <a href="https://github.com/castorini/anserini-notebooks/blob/master/pyserini_covid19_default.ipynb">notebooks using Pyserini</a>.</p>
<p>In order to provide the users a live system that can be used to answer questions, the team leveraged their earlier work on <a href="https://www.semanticscholar.org/paper/Solr-Integration-in-the-Anserini-Information-Clancy-Eskildsen/31fc159be43811170b9906c5809c1583e9778151">anserini integration with Solr</a> , open source search platform. The user search interface is built using Blacklight discovery interface with Ruby on Rails for faceting & highlighting.</p>
<p><img src="https://d3i71xaburhd42.cloudfront.net/31fc159be43811170b9906c5809c1583e9778151/2-Figure1-1.png" alt="alt text" /></p>
<h3 id="highlighting">Highlighting</h3>
<p>In addition to that the team also built a highlighting feature on of keyword search. This allows the user to quickly scan the results with the matched keywords in the document.</p>
<p>It is built using <a href="https://www.semanticscholar.org/paper/BioBERT%3A-a-pre-trained-biomedical-language-model-Lee-Yoon/1e43c7084bdcb6b3102afaf301cce10faead2702">BioBERT</a>. The idea behind it is that a) the candidate matched documents & convert them into sentences. b) Similarly the query is treated as a sentence. The sentences & query are in turn converted into its numerical representations (vectors). Top sentences closer to the query are obtained using the <a href="https://en.wikipedia.org/wiki/Cosine_similarity">cosine similarity</a>. The top-K words in the context are highlighted in these top sentences.</p>
<h2 id="neural-covidex-for-reranking">Neural Covidex for reranking</h2>
<p>The research group was already working on the neural architectures specifically applying transfer learning on retrieval/ranking based problems.</p>
<ul>
<li>BERT for query based Passage Ranking : Applying transfer learning for passage reranking pre-trained on MS-MARCO dataset</li>
<li>BERTserini for retrieval-based question answering: Incorporating Anserini Retriever to retrieve the top K segments of text followed by BERT based pre-trained model to retrieve the answer span.</li>
</ul>
<p>Typically the task of reranking is turn the problem into a classification task where we take the query, candidate_document & predict the target as (relevant, not-relevant). To avoid the costly operation of performing classification on the entire corpus, this is applied at the reranking stages. The engine gets the top K documents from the previous retrieval stage and rerank them using machine learning model. As part of reranking stage, the team leveraged Sequence to Sequence Model for reranking (Nogueira et al. 2020).</p>
<p>Stages involved in training the reranking model using Transfer Learning Methodology</p>
<p>Pre-training →Fine Tuning → Inference</p>
<ul>
<li><strong>[Pre-training]</strong> Transformer based Language Model trained on MS Marco dataset</li>
<li><strong>[Fine Tuning]</strong> Given a query q, document D, the model is fine tuned to predict the output as either <strong>true</strong> or <strong>false</strong> as targets indicating the relevance.</li>
<li><strong>[Inference]</strong> In reranking setting, for each candidate documents, predict the prob distribution of (relevant, non-relevant) and sort the scores of relevant doc(<strong>true outputs</strong>) alone.</li>
</ul>
<p>Training a language model and the encoder from this fined tuned language model is normally used for the downstream tasks like Classification in transfer learning methodology. But this method of applying Sequence to Sequence model (<a href="https://ai.googleblog.com/2020/02/exploring-transfer-learning-with-t5.html">based on T5</a>) is quite new for document ranking setting (Nogueira et al., 2020).</p>
<p>The reasoning provided was the predicted target words can capture the relatedness through pre-training. This is based on encoder-decoder architecture & uses a similar masked language modeling objective. Given a query, document the model is fine tuned to produce true or false if the document is relevant or not to the query.</p>
<h2 id="challenges-in-results-evaluation">Challenges in Results Evaluation</h2>
<ul>
<li>
<p>The authors rightfully mention that the individual components comprising such a system is evaluated against various test datasets. But as this is specific to an evolving dataset like CORD-19, there is no such existing test collections.</p>
</li>
<li>
<p>It is not always necessary that ranking is the most important for such an end to end system. We have to switch to an <strong>outcome based measure</strong> rather than a single output based measure like batch retrieval evaluations(MRR, nDCG). Eg: “Did the researchers, practitioners get their questions answered?” How many of them are not finding the answers? So involving human in the loop to qualitatively evaluate the results is essential to know if the system is really contributing towards the efforts fighting the pandemic.</p>
</li>
<li>
<p>What if the exploratory users do not know the right type of keywords to use ? In that case ranking is a wrong goal to pursue.</p>
</li>
<li>
<p>Current challenge is all the targeted users are working on the front line and hard to provide qualitative feedback about search experience. So the author asks for more hallway usability testing to gather insights from the users.</p>
</li>
</ul>
<h2 id="author-reflections">Author Reflections</h2>
<p>An end to end system like Covidex is not possible without the power of the current Open Source Software ecosystem, Open culture of curating, cleaning & sharing the data with the community (Thanks to CORD-19 by Allen AI) and pre-trained language models like MS-Marco etc.</p>
<p>Good software engineering practices is the foundation for a team and ensure that the underlying software components can be replicated & reused to provide this system. This is essential to rapidly explore and experiment with new ideas.</p>
<p>Building a strong research culture to produce the results in the form of open source software artifacts aid the community in reproducing the results and build on top of it.</p>
<p>Reminder about the mismatch between producing research code for conference and building a system for a real users. For example concerns like latency of search requests, throughput about the number of users, deploying & managing a system in production, user experience does not arise in a research setting.</p>
<h2 id="insights--takeaways-from-this-paper">Insights & Takeaways from this paper</h2>
<ul>
<li>Lack of proper training data & human annotators is a common challenge. Leveraging pre-trained models on MS-MARCO is critical for ranking tasks in this type of situation.</li>
<li>The experimentation mindset need to be adopted and one need to interactive computing tools like pyserini to experiment with search index. This allows the search practitioners to constantly iterate and learn from these experiments.</li>
<li>Adoption of Openness in not only the source but science and data & the way we work is truly inspiring.</li>
</ul>Paper Summary - Rapidly Deploying a Neural Search Engine for the COVID-19 Open Research Dataset