<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>ForBo7 // Salman Naqvi</title>
<link>https://forbo7.github.io/forblog/</link>
<atom:link href="https://forbo7.github.io/forblog/index.xml" rel="self" type="application/rss+xml"/>
<description>The world of ForBo7!</description>
<image>
<url>https://forbo7.github.io/images/profile.png</url>
<title>ForBo7 // Salman Naqvi</title>
<link>https://forbo7.github.io/forblog/</link>
</image>
<generator>quarto-1.9.37</generator>
<lastBuildDate>Fri, 17 Apr 2026 00:00:00 GMT</lastBuildDate>
<item>
  <title>Visualizing Compressed Latents</title>
  <dc:creator>Salman Naqvi</dc:creator>
  <link>https://forbo7.github.io/forblog/posts/35_vae_visualizer.html</link>
  <description><![CDATA[ 




<p><img src="https://forbo7.github.io/forblog/images/35_vae_visualizer/thumbnail.png" class="img-fluid"></p>
<div class="callout callout-style-simple callout-note">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>Thanks to <a href="https://www.johnowhitaker.com/">Jonothan Whitaker</a>’s <a href="https://github.com/fastai/diffusion-nbs/blob/master/stable_diffusion.ipynb">VAE implementation</a> in <a href="https://www.youtube.com/watch?v=0_BBRNYInx8">lesson 9a</a> of the fastai course.</p>
</div>
</div>
</div>
<p>This notebook is the source code for a VAE visualization app I created that allows you to see how the compressed latents look like, and tweak certain parameters that produce the latents. You can explore the app <a href="https://the-vae-visualizer.solveit.pub/">here</a>. Works best with images whose dimensions are multiples of 8.</p>
<section id="explore-the-vae" class="level2">
<h2 class="anchored" data-anchor-id="explore-the-vae">Explore the VAE</h2>
<div id="fa513160" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> diffusers <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> AutoencoderKL</span>
<span id="cb1-2">vae <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> AutoencoderKL.from_pretrained(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CompVis/stable-diffusion-v1-4"</span>, subfolder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"vae"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stderr">
<pre data-code-line-numbers=""><code>/usr/local/lib/python3.12/site-packages/huggingface_hub/utils/_validators.py:205: UserWarning: The `local_dir_use_symlinks` argument is deprecated and ignored in `hf_hub_download`. Downloading to a local directory does not use symlinks anymore.
  warnings.warn(
Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads.</code></pre>
</div>
</div>
<div id="4eed90f1" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>curl <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">--</span>output macaw.jpg <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'https://lafeber.com/pet-birds/wp-content/uploads/2018/06/Scarlet-Macaw-2.jpg'</span></span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed

  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100 58602  100 58602    0     0  1014k      0 --:--:-- --:--:-- --:--:-- 1021k</code></pre>
</div>
</div>
<div id="25740871" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> PIL <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Image</span>
<span id="cb5-2">img <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Image.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'macaw.jpg'</span>).resize((<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">512</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">512</span>))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> img</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="47">
<div>
<figure class="figure">
<p><img src="https://forbo7.github.io/forblog/posts/35_vae_visualizer_files/figure-html/cell-4-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>The image needs to be converted to a PyTorch tensor.</p>
<div id="c21be78a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> torch</span>
<span id="cb6-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> torchvision.transforms <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> v2</span>
<span id="cb6-3">v2.Compose([v2.ToImage(), v2.ToDtype(torch.float32, scale<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)])(img)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="48">
<pre data-code-line-numbers=""><code>Image([[[0.1804, 0.1804, 0.1804,  ..., 0.2392, 0.2392, 0.2431],
        [0.1843, 0.1843, 0.1843,  ..., 0.2392, 0.2392, 0.2431],
        [0.1843, 0.1882, 0.1882,  ..., 0.2431, 0.2431, 0.2431],
        ...,
        [0.8471, 0.8471, 0.8471,  ..., 0.5373, 0.5490, 0.5686],
        [0.8471, 0.8471, 0.8471,  ..., 0.5333, 0.5451, 0.5608],
        [0.8471, 0.8471, 0.8471,  ..., 0.5294, 0.5451, 0.5569]],

       [[0.1529, 0.1529, 0.1529,  ..., 0.2118, 0.2118, 0.2157],
        [0.1569, 0.1569, 0.1569,  ..., 0.2118, 0.2118, 0.2157],
        [0.1569, 0.1608, 0.1608,  ..., 0.2157, 0.2157, 0.2157],
        ...,
        [0.8196, 0.8196, 0.8196,  ..., 0.5569, 0.5647, 0.5843],
        [0.8196, 0.8196, 0.8196,  ..., 0.5569, 0.5647, 0.5765],
        [0.8196, 0.8196, 0.8196,  ..., 0.5529, 0.5608, 0.5725]],

       [[0.1843, 0.1843, 0.1843,  ..., 0.2431, 0.2431, 0.2471],
        [0.1882, 0.1882, 0.1882,  ..., 0.2431, 0.2431, 0.2471],
        [0.1882, 0.1922, 0.1922,  ..., 0.2471, 0.2471, 0.2471],
        ...,
        [0.7098, 0.7098, 0.7216,  ..., 0.5569, 0.5686, 0.5882],
        [0.7098, 0.7098, 0.7216,  ..., 0.5569, 0.5647, 0.5804],
        [0.7098, 0.7098, 0.7216,  ..., 0.5529, 0.5647, 0.5765]]], )</code></pre>
</div>
</div>
<div id="3b4a416e" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1">ToTensor <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> v2.Compose([v2.ToImage(), v2.ToDtype(torch.float32, scale<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)])<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> ToTensor</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="49">
<pre data-code-line-numbers=""><code>Compose(
      ToImage()
      ToDtype(scale=True)
)</code></pre>
</div>
</div>
<div id="44c6f66b" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1">ToTensor(img).shape, ToTensor(img)[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,...].shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="50">
<pre data-code-line-numbers=""><code>(torch.Size([3, 512, 512]), torch.Size([1, 3, 512, 512]))</code></pre>
</div>
</div>
<p><code>v2.ToDtype</code> needs to be usedd. Otherwise directly using <code>v2.ToImage</code> results in a <code>uint8</code> tensor</p>
<div id="73dd644d" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> torch</span>
<span id="cb12-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> torchvision.transforms <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> v2</span>
<span id="cb12-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> torch.no_grad():</span>
<span id="cb12-4">    lat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> vae.encode(ToTensor(img)[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>,...]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb12-5">    lat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.18215</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> lat.latent_dist.sample()</span></code></pre></div></div>
</div>
<div id="622918c8" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1">lat.shape, lat[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="52">
<pre data-code-line-numbers=""><code>(torch.Size([1, 4, 64, 64]), torch.Size([4, 64, 64]))</code></pre>
</div>
</div>
<div id="8348af97" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb15" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb15-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb15-2">fig,axs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>))</span>
<span id="cb15-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> c <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>): </span>
<span id="cb15-4">    axs[c].imshow(lat[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>][c], cmap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Greys'</span>)</span>
<span id="cb15-5">    axs[c].axis(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'off'</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://forbo7.github.io/forblog/posts/35_vae_visualizer_files/figure-html/cell-10-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
</section>
<section id="app" class="level2">
<h2 class="anchored" data-anchor-id="app">APP</h2>
<p>The app will be written with FastHTML. I will be previewing the app inline within this dialog. For this to work, I first tweak a Starlette setting so cookies also work within the inline previews.</p>
<div id="77053ce3" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> starlette.middleware.sessions <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> SessionMiddleware</span>
<span id="cb16-2"></span>
<span id="cb16-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> PartitionedSessionMiddleware(SessionMiddleware):</span>
<span id="cb16-4">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs):</span>
<span id="cb16-5">        <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">super</span>().<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs)</span>
<span id="cb16-6">        <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.security_flags <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"; partitioned"</span></span></code></pre></div></div>
</div>
<p>Now I define the app.</p>
<div id="a96faed6" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb17" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb17-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fasthtml.common <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span></span>
<span id="cb17-2"></span>
<span id="cb17-3">app <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FastHTML(hdrs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(picolink, MarkdownJS(), HighlightJS()), debug<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, session_cookie<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'vae_app'</span>, same_site<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'none'</span>, sess_https_only<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, sess_cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>PartitionedSessionMiddleware)</span>
<span id="cb17-4">rt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> app.route</span></code></pre></div></div>
</div>
<p>Now I write the code that will allow me to preview the app inline.</p>
<div id="0d0b5faa" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb18" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> functools <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> partial</span>
<span id="cb18-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fasthtml.jupyter <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span></span>
<span id="cb18-3"></span>
<span id="cb18-4">port <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8002</span></span>
<span id="cb18-5">url <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'the-vae-visualizer.solveit.pub'</span></span>
<span id="cb18-6">server <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> JupyUvi(app, port<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>port)</span></code></pre></div></div>
</div>
<div id="3e7b1f85" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb19" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb19-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_preview(app): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> partial(HTMX, app<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>app, host<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>url, port<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">443</span>)</span>
<span id="cb19-2">prev <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_preview(app)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> prev()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="57">
<iframe src="https://the-vae-visualizer.solveit.pub:443/" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<div id="ebc3ba52" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb20" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb20-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> p(component):</span>
<span id="cb20-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">hasattr</span>(component, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'app'</span>): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> prev(component)</span>
<span id="cb20-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>:</span>
<span id="cb20-4">        <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb20-5">        <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> _test(): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> component</span>
<span id="cb20-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> prev(_test)</span>
<span id="cb20-7">p(Input())</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="58">
<iframe srcdoc="<!doctype html>
<html>
  <head>
    <title>FastHTML page</title>
    <link rel=&quot;canonical&quot; href=&quot;https://testserver/_L_q6hOucRUKvonFqP8SMzg&quot;>
    <meta charset=&quot;utf-8&quot;>
    <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script>    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/@picocss/pico@latest/css/pico.min.css&quot;>
    <style>:root { --pico-font-size: 100%; }</style>
<script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>  </head>
  <body>
    <input>
  </body>
</html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<div id="33089393" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb21" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb21-1">render_ft()</span></code></pre></div></div>
</div>
<p><code>render_ft</code> enables rendering of HTML components inline.</p>
<section id="localization" class="level3">
<h3 class="anchored" data-anchor-id="localization">Localization</h3>
<div id="6b6aecf1" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb22" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb22-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> contextvars <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> ContextVar</span>
<span id="cb22-2">current_lang <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ContextVar(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'lang'</span>, default<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'zh'</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> current_lang</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="60">
<pre data-code-line-numbers=""><code>&lt;ContextVar name='lang' default='zh' at 0x75bbc4baab10&gt;</code></pre>
</div>
</div>
<p>When a user accesses this application, <code>ContextVar</code> will give each request its own independent copy of a variable. In this way, different values of <code>current_lang</code> can be kept on the same instance.</p>
<div id="67ed0097" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb24" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb24-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb24-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> setsession(session):</span>
<span id="cb24-3">    current_lang.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(session.setdefault(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'lang'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'zh'</span>))</span></code></pre></div></div>
</div>
<div id="c4c16d0e" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb25" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb25-1">T <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb25-2">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'zh'</span>: {</span>
<span id="cb25-3">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'title'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'VAE 压缩探索器'</span>,</span>
<span id="cb25-4">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'process'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'开始处理'</span>,</span>
<span id="cb25-5">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'advanced_settings'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'高级设置'</span>,</span>
<span id="cb25-6">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'image_label'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'图片'</span>,</span>
<span id="cb25-7">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'vae_scale_label'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'VAE 缩放'</span>,</span>
<span id="cb25-8">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'vae_scale_tip'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'归一化潜在空间，匹配噪声调度器的尺度'</span>,</span>
<span id="cb25-9">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_one_label'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'归一化因子1'</span>,</span>
<span id="cb25-10">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_two_label'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'归一化因子2'</span>,</span>
<span id="cb25-11">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_tip'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'将像素值从 [0,1] 映射到 [-1,1]，匹配 VAE 训练分布'</span>,</span>
<span id="cb25-12">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'no_result'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'这里还空着呢～'</span>,</span>
<span id="cb25-13">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'error_msg'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'❌ 错误：'</span>,</span>
<span id="cb25-14">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'vae_scale_desc'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'VAE 缩放系数继承自 Stable Diffusion 1.4。它对潜在空间进行缩放，使其方差与噪声调度器的预期尺度保持一致，防止迭代采样过程中的漂移。'</span>,</span>
<span id="cb25-15">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_desc'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Norm 参数负责将像素值从 [0,1] 重映射到 [-1,1]，以匹配 VAE 训练时使用的像素值。如果有一组 0 到 1 之间的值，乘以 2 再减去 1，就能将它们转换到 -1 到 1 的范围。'</span>,</span>
<span id="cb25-16">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'footer'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'版本 0.0.1 | 使用 '</span>,</span>
<span id="cb25-17">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'crafted_by'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">' 制作'</span>,</span>
<span id="cb25-18">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'name'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'纳克威·萨尔曼'</span></span>
<span id="cb25-19">    },</span>
<span id="cb25-20">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'en'</span>: {</span>
<span id="cb25-21">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'title'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'VAE Compression Explorer'</span>,</span>
<span id="cb25-22">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'process'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Process'</span>,</span>
<span id="cb25-23">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'advanced_settings'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Advanced Settings'</span>,</span>
<span id="cb25-24">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'image_label'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Image'</span>,</span>
<span id="cb25-25">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'vae_scale_label'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'VAE Scale'</span>,</span>
<span id="cb25-26">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'vae_scale_tip'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Normalizes latent variance to align with the noise scheduler's scale"</span>,</span>
<span id="cb25-27">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_one_label'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Norm 1'</span>,</span>
<span id="cb25-28">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_two_label'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Norm 2'</span>,</span>
<span id="cb25-29">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_tip'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Rescales pixel values from [0,1] to [-1,1] to match VAE training distribution'</span>,</span>
<span id="cb25-30">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'no_result'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Nothing here yet!'</span>,</span>
<span id="cb25-31">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'error_msg'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'❌ Error: '</span>,</span>
<span id="cb25-32">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'vae_scale_desc'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'The VAE Scale is a variance normalization constant inherited from Stable Diffusion 1.4. It scales the latent so its variance is consistent with the noise scheduler</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\'</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">s expected scale. This prevents drift during the iterative sampling process.'</span>,</span>
<span id="cb25-33">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_desc'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'The "Norm" parameters are responsible for remapping pixel values from [0,1] to [-1,1], matching the pixel values the VAE was trained on. If we have a set of values betweeen 0 and 1, multiply them by 2, and then subtract one, we</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\'</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">ve transformed that set of values to be between -1 and 1.'</span>,</span>
<span id="cb25-34">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'footer'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Version 0.0.1 | Crafted with '</span>,</span>
<span id="cb25-35">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'crafted_by'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">' by '</span>,</span>
<span id="cb25-36">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'name'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Salman Naqvi'</span></span>
<span id="cb25-37">    }</span>
<span id="cb25-38">}</span></code></pre></div></div>
</div>
<div id="37df0745" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb26" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb26-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> t(key, session<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>):</span>
<span id="cb26-2">    lang <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> session.get(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'lang'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'zh'</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> session <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> current_lang.get()</span>
<span id="cb26-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> T[lang].get(key, key)</span></code></pre></div></div>
</div>
<div id="0e2aa571" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb27" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb27-1">t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'title'</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="64">
<pre data-code-line-numbers=""><code>'VAE 压缩探索器'</code></pre>
</div>
</div>
</section>
<section id="vae-compression" class="level3">
<h3 class="anchored" data-anchor-id="vae-compression">VAE Compression</h3>
<div id="46bb4b88" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb29" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb29-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> img2lat(img, scale, nconst1, nconst2):</span>
<span id="cb29-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> torch.no_grad():</span>
<span id="cb29-3">        lat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> vae.encode(ToTensor(img)[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, ...]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>nconst1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>nconst2)</span>
<span id="cb29-4">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> scale <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> lat.latent_dist.sample()</span>
<span id="cb29-5"></span>
<span id="cb29-6"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> lat2img(lat, scale, nconst1, nconst2):</span>
<span id="cb29-7">    lat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>scale</span>
<span id="cb29-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> torch.no_grad(): img <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> vae.decode(lat).sample</span>
<span id="cb29-9">    img <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ((img<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>nconst2)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>nconst1).clamp(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb29-10">    img <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> img.detach().permute(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).numpy()</span>
<span id="cb29-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Image.fromarray((img<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">255</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>().astype(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'uint8'</span>)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])</span>
<span id="cb29-12"></span>
<span id="cb29-13"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> lat2plot(lat):</span>
<span id="cb29-14">    fig,axs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plt.subplots(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, figsize<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>))</span>
<span id="cb29-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> c <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>):</span>
<span id="cb29-16">        axs[c].imshow(lat[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>][c], cmap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Greys'</span>)</span>
<span id="cb29-17">        axs[c].axis(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'off'</span>)</span>
<span id="cb29-18">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> fig</span></code></pre></div></div>
</div>
<div id="fa095683" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb30" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb30-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> io <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> BytesIO</span>
<span id="cb30-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> base64 <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> b64encode</span>
<span id="cb30-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> process(fbytes, scale<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.18215</span>, nconst1<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, nconst2<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>):</span>
<span id="cb30-4">    oimg <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Image.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(BytesIO(fbytes)).resize((<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">512</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">512</span>))</span>
<span id="cb30-5">    lat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> img2lat(oimg, scale, nconst1, nconst2)</span>
<span id="cb30-6">    fig <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> lat2plot(lat)</span>
<span id="cb30-7">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># pimg = lat2img(lat, scale, nconst1, nconst2)</span></span>
<span id="cb30-8">        </span>
<span id="cb30-9">    buf1, buf2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> BytesIO(), BytesIO()</span>
<span id="cb30-10">    fig .savefig(buf1, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">format</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'png'</span>)</span>
<span id="cb30-11">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># pimg.save   (buf2, format='png')</span></span>
<span id="cb30-12">    oimg.save   (buf2, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">format</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'png'</span>)</span>
<span id="cb30-13">    </span>
<span id="cb30-14">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> buf2b64(buf): buf.seek(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> b64encode(buf.read()).decode()</span>
<span id="cb30-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> mapt(buf2b64, [buf1,buf2])</span></code></pre></div></div>
</div>
<p>I use <code>BytesIO</code> to avoid having to save the image to disk. <code>process</code> returns a base64 representation so the image can be directly rendered in the browser.</p>
<div id="70159668" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb31" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb31-1">buf <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> BytesIO()</span>
<span id="cb31-2">img.save(buf, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">format</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'png'</span>)</span>
<span id="cb31-3">buf.seek(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb31-4">a, b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> process(fbytes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>buf.getvalue())</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://forbo7.github.io/forblog/posts/35_vae_visualizer_files/figure-html/cell-24-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="3d4dc850" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb32" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb32-1">a[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">200</span>], b[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">200</span>]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="68">
<pre data-code-line-numbers=""><code>('iVBORw0KGgoAAAANSUhEUgAABkAAAAGQCAYAAAD2lawGAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAsqJJREFUeJztvXvwntdZnvuEHjgUEmM7',
 'iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAIAAAB7GkOtAAEAAElEQVR4nKz9Sbdlu44uhn0f5toRcc65WTy9J0vDsp6b6tn//6e442F37DGeLOWtThGxFwE3QIBgMdfeN1Mz88ZZe04WIIiKIAjy//a//N8BACBJEuVZ3uTvpVi+MbO9lpmJiKrW6lkS98/Staqamb9c')</code></pre>
</div>
</div>
</section>
<section id="upload-route" class="level3">
<h3 class="anchored" data-anchor-id="upload-route">Upload Route</h3>
<div id="6a3f6476" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb34" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb34-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> base64 <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> b64encode</span>
<span id="cb34-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> io <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> BytesIO</span>
<span id="cb34-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> PIL <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Image</span>
<span id="cb34-4"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb34-5"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">async</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> upload(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">file</span>:UploadFile, vae_scale:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>, norm_one:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>, norm_two:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>): </span>
<span id="cb34-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>:</span>
<span id="cb34-7">        fbytes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">await</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">file</span>.read()</span>
<span id="cb34-8">        lat_b64, proc_b64 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> process(fbytes, vae_scale, norm_one, norm_two)</span>
<span id="cb34-9">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Div(style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"display:flex; flex-direction:column"</span>)(</span>
<span id="cb34-10">            Img(src<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'data:image/jpeg;base64,</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>lat_b64<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>, style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max-width:800px; width: 100%'</span>),</span>
<span id="cb34-11">            Img(src<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'data:image/jpeg;base64,</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>proc_b64<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>, style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'max-width:800px; width: 50%; display:block; margin:auto'</span>),</span>
<span id="cb34-12">        )</span>
<span id="cb34-13">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">except</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">Exception</span> <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> e: <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Article(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'error_msg'</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}{</span>e<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"color: var(--pico-del-color); border-color: var(--pico-del-color);"</span>)</span></code></pre></div></div>
</div>
<div id="3b7ec223" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb35" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb35-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> starlette.datastructures <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> UploadFile</span>
<span id="cb35-2">buf.seek(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb35-3">uf <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> UploadFile(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">file</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>buf)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> uf</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="70">
<pre data-code-line-numbers=""><code>UploadFile(filename=None, size=None, headers=Headers({}))</code></pre>
</div>
</div>
<div id="489c9a13" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb37" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb37-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># </span></span>
<span id="cb37-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># await upload(uf, 0.18215, 2, 1)</span></span></code></pre></div></div>
</div>
</section>
<section id="dashboard" class="level3">
<h3 class="anchored" data-anchor-id="dashboard">Dashboard</h3>
<div id="1141f410" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb38" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb38-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> fasthtml.components <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> fc</span>
<span id="cb38-2"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@delegates</span>(fc.Input)</span>
<span id="cb38-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> LabelledInput(lbl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, tip<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs): </span>
<span id="cb38-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> name <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"id or name required"</span></span>
<span id="cb38-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Div(style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'flex-direction:column'</span>)(</span>
<span id="cb38-6">        fc.Label(lbl, data_tooltip<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>tip, fr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'inp-</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'lbl-</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>), </span>
<span id="cb38-7">        fc.Input(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'inp-</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>, name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>name, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs)</span>
<span id="cb38-8">    )</span></code></pre></div></div>
</div>
<p>I’ve overwritten <code>Input</code> so it always has a <code>Label</code> component attached to it.</p>
<div id="f3b16c1e" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb39" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb39-1">p(LabelledInput(placeholder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'hehe'</span>, name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'testing'</span>, tip<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'LOL'</span>, lbl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'haha'</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="73">
<iframe srcdoc="<!doctype html>
<html>
  <head>
    <title>FastHTML page</title>
    <link rel=&quot;canonical&quot; href=&quot;https://testserver/_IKD1OAR6Sl2gdxYVHs_X6w&quot;>
    <meta charset=&quot;utf-8&quot;>
    <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script>    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/@picocss/pico@latest/css/pico.min.css&quot;>
    <style>:root { --pico-font-size: 100%; }</style>
<script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>  </head>
  <body>
    <div style=&quot;flex-direction:column&quot;>
<label data-tooltip=&quot;LOL&quot; for=&quot;inp-testing&quot; id=&quot;lbl-testing&quot;>haha</label>      <input name=&quot;testing&quot; placeholder=&quot;hehe&quot; id=&quot;inp-testing&quot;>
    </div>
  </body>
</html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<div id="b22b98b6" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb40" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb40-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> Dashboard():</span>
<span id="cb40-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Card(style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'flex:2'</span>)(</span>
<span id="cb40-3">        Form(hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>upload, hx_target<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#res'</span>, hx_swap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'innerHTML'</span>,</span>
<span id="cb40-4">             hx_indicator<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#loading'</span>, hx_disabled_elt<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#process-btn, #upload-inp'</span>,</span>
<span id="cb40-5">             enctype<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"multipart/form-data"</span>)(</span>
<span id="cb40-6">            UploadWidget(),</span>
<span id="cb40-7">            Div(style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'margin-top: 1rem'</span>)(SettingsWidget()),</span>
<span id="cb40-8">        )</span>
<span id="cb40-9">    )</span></code></pre></div></div>
</div>
<div id="7a73f779" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb41" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb41-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> UploadWidget():</span>
<span id="cb41-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Div(style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'display:flex; align-items:center; gap:0.5rem'</span>)(</span>
<span id="cb41-3">        UploadInput(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'image_label'</span>), name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'file'</span>),</span>
<span id="cb41-4">        Button(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'process'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'submit'</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'process-btn'</span>, style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'margin-bottom:0;'</span>),</span>
<span id="cb41-5">    )</span></code></pre></div></div>
</div>
<div id="2ccb16d1" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb42" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb42-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@delegates</span>(fc.Input)</span>
<span id="cb42-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> UploadInput(lbl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs): </span>
<span id="cb42-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> name <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">is</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"id or name required"</span></span>
<span id="cb42-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Div()(</span>
<span id="cb42-5">        fc.Label(style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'margin-bottom:0'</span>, role<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'button'</span>)(lbl, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"lbl-</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, fr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"inp-</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>),</span>
<span id="cb42-6">        fc.Input(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"inp-</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>name, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'file'</span>, accept<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'image/*'</span>, style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'display:none; margin-bottom:0'</span>, onchange<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"this.previousElementSibling.style.backgroundColor = this.files[0] ? 'green' : ''"</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs),</span>
<span id="cb42-7">    )</span></code></pre></div></div>
</div>
<div id="bb7c8190" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb43" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb43-1">p(UploadInput(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test'</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test'</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="77">
<iframe srcdoc="<!doctype html>
<html>
  <head>
    <title>FastHTML page</title>
    <link rel=&quot;canonical&quot; href=&quot;https://testserver/_F3oBoADXTfCOXtoI8l6eBQ&quot;>
    <meta charset=&quot;utf-8&quot;>
    <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script>    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/@picocss/pico@latest/css/pico.min.css&quot;>
    <style>:root { --pico-font-size: 100%; }</style>
<script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>  </head>
  <body>
    <div>
<label role=&quot;button&quot; style=&quot;margin-bottom:0&quot; id=&quot;lbl-test&quot; for=&quot;inp-test&quot;>test</label>      <input type=&quot;file&quot; accept=&quot;image/*&quot; onchange=&quot;this.previousElementSibling.style.backgroundColor = this.files[0] ? 'green' : ''&quot; id=&quot;inp-test&quot; style=&quot;display:none; margin-bottom:0&quot; name=&quot;inp-test&quot;>
    </div>
  </body>
</html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<div id="b937787d" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb44" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb44-1">p(UploadWidget())</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="78">
<iframe srcdoc="<!doctype html>
<html>
  <head>
    <title>FastHTML page</title>
    <link rel=&quot;canonical&quot; href=&quot;https://testserver/_FyEny0VUT_Kx6di7XM-G0A&quot;>
    <meta charset=&quot;utf-8&quot;>
    <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script>    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/@picocss/pico@latest/css/pico.min.css&quot;>
    <style>:root { --pico-font-size: 100%; }</style>
<script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>  </head>
  <body>
    <div style=&quot;display:flex; align-items:center; gap:0.5rem&quot;>
      <div>
<label role=&quot;button&quot; style=&quot;margin-bottom:0&quot; id=&quot;lbl-file&quot; for=&quot;inp-file&quot;>图片</label>        <input name=&quot;file&quot; type=&quot;file&quot; accept=&quot;image/*&quot; onchange=&quot;this.previousElementSibling.style.backgroundColor = this.files[0] ? 'green' : ''&quot; id=&quot;inp-file&quot; style=&quot;display:none; margin-bottom:0&quot;>
      </div>
<button type=&quot;submit&quot; id=&quot;process-btn&quot; style=&quot;margin-bottom:0;&quot; name=&quot;process-btn&quot;>开始处理</button>    </div>
  </body>
</html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<div id="9a41ba2a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb45" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb45-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> SettingsWidget():</span>
<span id="cb45-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Details(</span>
<span id="cb45-3">        Summary(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'advanced_settings'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'adv-summary'</span>),</span>
<span id="cb45-4">        Div(style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'display:flex; gap:1rem;'</span>)(</span>
<span id="cb45-5">            LabelledInput(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'number'</span>, name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'vae_scale'</span>, value<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.18215</span>, step<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'any'</span>,</span>
<span id="cb45-6">                lbl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'vae_scale_label'</span>), tip<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'vae_scale_tip'</span>)),</span>
<span id="cb45-7">            LabelledInput(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'number'</span>, name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_one'</span>, value<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,</span>
<span id="cb45-8">                lbl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_one_label'</span>), tip<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_tip'</span>)),</span>
<span id="cb45-9">            LabelledInput(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'number'</span>, name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_two'</span>, value<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb45-10">                lbl<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_two_label'</span>), tip<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_tip'</span>)),</span>
<span id="cb45-11">        ),</span>
<span id="cb45-12">        P(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'vae_scale_desc'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'vae-scale-desc'</span>),</span>
<span id="cb45-13">        P(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_desc'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm-desc'</span>)</span>
<span id="cb45-14">    )</span></code></pre></div></div>
</div>
<div id="46369cf1" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb46" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb46-1">p(SettingsWidget())</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="80">
<iframe srcdoc="<!doctype html>
<html>
  <head>
    <title>FastHTML page</title>
    <link rel=&quot;canonical&quot; href=&quot;https://testserver/_HtsGzo_LTWSVDU8DKRzN2A&quot;>
    <meta charset=&quot;utf-8&quot;>
    <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script>    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/@picocss/pico@latest/css/pico.min.css&quot;>
    <style>:root { --pico-font-size: 100%; }</style>
<script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>  </head>
  <body>
<details><summary id=&quot;adv-summary&quot;>高级设置</summary>      <div style=&quot;display:flex; gap:1rem;&quot;>
        <div style=&quot;flex-direction:column&quot;>
<label data-tooltip=&quot;归一化潜在空间，匹配噪声调度器的尺度&quot; for=&quot;inp-vae_scale&quot; id=&quot;lbl-vae_scale&quot;>VAE 缩放</label>          <input name=&quot;vae_scale&quot; type=&quot;number&quot; value=&quot;0.18215&quot; step=&quot;any&quot; id=&quot;inp-vae_scale&quot;>
        </div>
        <div style=&quot;flex-direction:column&quot;>
<label data-tooltip=&quot;将像素值从 [0,1] 映射到 [-1,1]，匹配 VAE 训练分布&quot; for=&quot;inp-norm_one&quot; id=&quot;lbl-norm_one&quot;>归一化因子1</label>          <input name=&quot;norm_one&quot; type=&quot;number&quot; value=&quot;2&quot; id=&quot;inp-norm_one&quot;>
        </div>
        <div style=&quot;flex-direction:column&quot;>
<label data-tooltip=&quot;将像素值从 [0,1] 映射到 [-1,1]，匹配 VAE 训练分布&quot; for=&quot;inp-norm_two&quot; id=&quot;lbl-norm_two&quot;>归一化因子2</label>          <input name=&quot;norm_two&quot; type=&quot;number&quot; value=&quot;1&quot; id=&quot;inp-norm_two&quot;>
        </div>
      </div>
      <p id=&quot;vae-scale-desc&quot;>VAE 缩放系数继承自 Stable Diffusion 1.4。它对潜在空间进行缩放，使其方差与噪声调度器的预期尺度保持一致，防止迭代采样过程中的漂移。</p>
      <p id=&quot;norm-desc&quot;>Norm 参数负责将像素值从 [0,1] 重映射到 [-1,1]，以匹配 VAE 训练时使用的像素值。如果有一组 0 到 1 之间的值，乘以 2 再减去 1，就能将它们转换到 -1 到 1 的范围。</p>
</details>  </body>
</html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<div id="e3769b8b" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb47" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb47-1">p(Dashboard())</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="81">
<iframe srcdoc="<!doctype html>
<html>
  <head>
    <title>FastHTML page</title>
    <link rel=&quot;canonical&quot; href=&quot;https://testserver/_w5fJstg7RxCL_iKSg2xXrQ&quot;>
    <meta charset=&quot;utf-8&quot;>
    <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script>    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/@picocss/pico@latest/css/pico.min.css&quot;>
    <style>:root { --pico-font-size: 100%; }</style>
<script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>    <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>  </head>
  <body>
    <article style=&quot;flex:2&quot;>
<form enctype=&quot;multipart/form-data&quot; hx-post=&quot;/upload&quot; hx-swap=&quot;innerHTML&quot; hx-indicator=&quot;#loading&quot; hx-disabled-elt=&quot;#process-btn, #upload-inp&quot; hx-target=&quot;#res&quot;>        <div style=&quot;display:flex; align-items:center; gap:0.5rem&quot;>
          <div>
<label role=&quot;button&quot; style=&quot;margin-bottom:0&quot; id=&quot;lbl-file&quot; for=&quot;inp-file&quot;>图片</label>            <input name=&quot;file&quot; type=&quot;file&quot; accept=&quot;image/*&quot; onchange=&quot;this.previousElementSibling.style.backgroundColor = this.files[0] ? 'green' : ''&quot; id=&quot;inp-file&quot; style=&quot;display:none; margin-bottom:0&quot;>
          </div>
<button type=&quot;submit&quot; id=&quot;process-btn&quot; style=&quot;margin-bottom:0;&quot; name=&quot;process-btn&quot;>开始处理</button>        </div>
        <div style=&quot;margin-top: 1rem&quot;>
<details><summary id=&quot;adv-summary&quot;>高级设置</summary>            <div style=&quot;display:flex; gap:1rem;&quot;>
              <div style=&quot;flex-direction:column&quot;>
<label data-tooltip=&quot;归一化潜在空间，匹配噪声调度器的尺度&quot; for=&quot;inp-vae_scale&quot; id=&quot;lbl-vae_scale&quot;>VAE 缩放</label>                <input name=&quot;vae_scale&quot; type=&quot;number&quot; value=&quot;0.18215&quot; step=&quot;any&quot; id=&quot;inp-vae_scale&quot;>
              </div>
              <div style=&quot;flex-direction:column&quot;>
<label data-tooltip=&quot;将像素值从 [0,1] 映射到 [-1,1]，匹配 VAE 训练分布&quot; for=&quot;inp-norm_one&quot; id=&quot;lbl-norm_one&quot;>归一化因子1</label>                <input name=&quot;norm_one&quot; type=&quot;number&quot; value=&quot;2&quot; id=&quot;inp-norm_one&quot;>
              </div>
              <div style=&quot;flex-direction:column&quot;>
<label data-tooltip=&quot;将像素值从 [0,1] 映射到 [-1,1]，匹配 VAE 训练分布&quot; for=&quot;inp-norm_two&quot; id=&quot;lbl-norm_two&quot;>归一化因子2</label>                <input name=&quot;norm_two&quot; type=&quot;number&quot; value=&quot;1&quot; id=&quot;inp-norm_two&quot;>
              </div>
            </div>
            <p id=&quot;vae-scale-desc&quot;>VAE 缩放系数继承自 Stable Diffusion 1.4。它对潜在空间进行缩放，使其方差与噪声调度器的预期尺度保持一致，防止迭代采样过程中的漂移。</p>
            <p id=&quot;norm-desc&quot;>Norm 参数负责将像素值从 [0,1] 重映射到 [-1,1]，以匹配 VAE 训练时使用的像素值。如果有一组 0 到 1 之间的值，乘以 2 再减去 1，就能将它们转换到 -1 到 1 的范围。</p>
</details>        </div>
</form>    </article>
  </body>
</html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
</section>
<section id="main" class="level3">
<h3 class="anchored" data-anchor-id="main">Main</h3>
<p>I’ll first define route that’ll toggle language, before writing the index page.</p>
<div id="8d7a1c48" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb48" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb48-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb48-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> toggle_lang(session):</span>
<span id="cb48-3">    lang <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'en'</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> session.get(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'lang'</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'zh'</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'zh'</span></span>
<span id="cb48-4">    current_lang.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(lang)</span>
<span id="cb48-5">    session[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'lang'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> lang</span>
<span id="cb48-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> (</span>
<span id="cb48-7">        Button(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'process'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'submit'</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'process-btn'</span>, hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'true'</span>, style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'margin-bottom:0'</span>),</span>
<span id="cb48-8">        H1(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'title'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'title'</span>, hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'true'</span>),</span>
<span id="cb48-9">        Summary(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'advanced_settings'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'adv-summary'</span>, hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'true'</span>),</span>
<span id="cb48-10">        Div(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'res'</span>, style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'display:flex; align-items:center; justify-content:center; flex:1'</span>, hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'true'</span>)(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'no_result'</span>)),</span>
<span id="cb48-11">        Label(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'image_label'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'lbl-file'</span>, fr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'inp-file'</span>, role<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'button'</span>, hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'true'</span>, style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'margin-bottom:0'</span>),</span>
<span id="cb48-12">        Label(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'vae_scale_label'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'lbl-vae_scale'</span>, fr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'vae_scale'</span>, hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'true'</span>, data_tooltip<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'vae_scale_tip'</span>)),</span>
<span id="cb48-13">        Label(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_one_label'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'lbl-norm_one'</span>, fr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_one'</span>, hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'true'</span>, data_tooltip<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_tip'</span>)),</span>
<span id="cb48-14">        Label(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_two_label'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'lbl-norm_two'</span>, fr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_two'</span>, hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'true'</span>, data_tooltip<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_tip'</span>)),</span>
<span id="cb48-15">        P(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'vae_scale_desc'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'vae-scale-desc'</span>, hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'true'</span>),</span>
<span id="cb48-16">        P(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm_desc'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'norm-desc'</span>, hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'true'</span>),</span>
<span id="cb48-17">        Footer(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'footer'</span>, hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'true'</span>, style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'color: var(--pico-muted-color);'</span>)(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'footer'</span>), A(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'FastHTML'</span>, href<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'https://fastht.ml'</span>), t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'crafted_by'</span>), A(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'name'</span>), href<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'https://forbo7.github.io/'</span>))</span>
<span id="cb48-18">    )</span></code></pre></div></div>
</div>
<div id="b49ff682" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb49" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb49-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb49-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> index(session): </span>
<span id="cb49-3">    setsession(session)</span>
<span id="cb49-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Card(style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"padding: 2rem; max-width: 1200px; margin: 2rem auto;"</span>)(</span>
<span id="cb49-5">        Div(style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"display:flex; align-items:center; gap:1rem; margin-bottom:2rem"</span>)(</span>
<span id="cb49-6">            H1(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'title'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'title'</span>),</span>
<span id="cb49-7">            Button(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'🌐'</span>, hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>toggle_lang, hx_swap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'none'</span>),</span>
<span id="cb49-8">            Div(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'loading'</span>, aria_busy<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'true'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'htmx-indicator'</span>)(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>),</span>
<span id="cb49-9">        ),</span>
<span id="cb49-10">        Div(style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"display:flex; gap:1rem; align-items:stretch"</span>)(</span>
<span id="cb49-11">            Dashboard(),</span>
<span id="cb49-12">            Card(style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'flex:3; margin-top:1rem; display:flex; flex-direction:column; align-items:center; min-height: 200px;'</span>)(</span>
<span id="cb49-13">                Div(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'res'</span>, style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'display:flex; align-items:center; justify-content:center; flex:1'</span>)(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'no_result'</span>)),</span>
<span id="cb49-14">            )</span>
<span id="cb49-15">        ),</span>
<span id="cb49-16">        Footer(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'footer'</span>, style<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'color: var(--pico-muted-color);'</span>)(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'footer'</span>), A(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'FastHTML'</span>, href<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'https://fastht.ml'</span>), t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'crafted_by'</span>), A(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'name'</span>), href<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'https://forbo7.github.io/'</span>))</span>
<span id="cb49-17">    )</span>
<span id="cb49-18"></span>
<span id="cb49-19">prev(index)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="83">
<iframe src="https://the-vae-visualizer.solveit.pub:443/" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<hr>
<p>If you have any comments, questions, suggestions, feedback, criticisms, or corrections, please do post them down in the comment section below!</p>


</section>
</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>HTML</category>
  <category>Diffusion</category>
  <category>Analyzing Models</category>
  <guid>https://forbo7.github.io/forblog/posts/35_vae_visualizer.html</guid>
  <pubDate>Fri, 17 Apr 2026 00:00:00 GMT</pubDate>
  <media:content url="https://forbo7.github.io/forblog/images/35_vae_visualizer/thumbnail.png" medium="image" type="image/png" height="90" width="144"/>
</item>
<item>
  <title>Working with Bytes in Python</title>
  <dc:creator>Salman Naqvi</dc:creator>
  <link>https://forbo7.github.io/forblog/posts/34_working_with_bytes.html</link>
  <description><![CDATA[ 




<p><img src="https://forbo7.github.io/forblog/images/34_working_with_bytes/thumbnail.png" class="img-fluid"></p>
<p>Instantiate a buffer in memory.</p>
<div id="377027eb" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> io <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> BytesIO</span>
<span id="cb1-2">buf <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> BytesIO()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> buf</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="23">
<pre data-code-line-numbers=""><code>&lt;_io.BytesIO at 0x7e185d719350&gt;</code></pre>
</div>
</div>
<p>Now you can’t directly write data to this buffer.</p>
<div id="20064b95" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1">buf.write(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'This is some data'</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-error">
<div class="ansi-escaped-output">
<pre><span class="ansi-red-fg">---------------------------------------------------------------------------</span>
<span class="ansi-red-fg">TypeError</span>                                 Traceback (most recent call last)
<span class="ansi-cyan-fg">Cell</span><span class="ansi-cyan-fg"> </span><span class="ansi-green-fg">In[24]</span><span class="ansi-green-fg">, line 1</span>
<span class="ansi-green-fg">----&gt; </span><span class="ansi-green-fg">1</span> buf.write(<span class="ansi-yellow-fg">'This is some data'</span>)

<span class="ansi-red-fg">TypeError</span>: a bytes-like object is required, not 'str'</pre>
</div>
</div>
</div>
<p>You need a bytes-like object.</p>
<div id="9281f68f" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1">buf.write(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">b'This is some data'</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="25">
<pre data-code-line-numbers=""><code>17</code></pre>
</div>
</div>
<p>17 bytes have been written to memory, which we can confirm here.</p>
<div id="38609f9f" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">b'This is some data'</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="26">
<pre data-code-line-numbers=""><code>17</code></pre>
</div>
</div>
<div id="571b75b5" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">b'This is some data'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'This is some data'</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="78">
<pre data-code-line-numbers=""><code>(bytes, str)</code></pre>
</div>
</div>
<div id="b7f53a9d" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1">buf.getvalue()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="28">
<pre data-code-line-numbers=""><code>b'This is some data'</code></pre>
</div>
</div>
<p>Behind the scenes, the data is stored as binary. However, when printed out, if the byte is a printable character, Python directly renders it out.</p>
<p>We can view the bytes as hexadecimal.</p>
<div id="32e4caf9" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1">buf.getvalue().<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">hex</span>()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="53">
<pre data-code-line-numbers=""><code>'5468697320697320736f6d652064617461'</code></pre>
</div>
</div>
<div id="8edeb785" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> textwrap <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> wrap</span>
<span id="cb14-2">h <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> buf.getvalue().<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">hex</span>()</span>
<span id="cb14-3">wrap(h, width<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="67">
<pre data-code-line-numbers=""><code>['54',
 '68',
 '69',
 '73',
 '20',
 '69',
 '73',
 '20',
 '73',
 '6f',
 '6d',
 '65',
 '20',
 '64',
 '61',
 '74',
 '61']</code></pre>
</div>
</div>
<div id="42b6752c" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1">?<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">chr</span></span></code></pre></div></div>
<div class="cell-output cell-output-display cell-output-markdown">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb17" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb17-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">chr</span>(</span>
<span id="cb17-2">    i</span>
<span id="cb17-3">):</span></code></pre></div></div>
<pre data-code-line-numbers=""><code>Return a Unicode string of one character with ordinal i; 0 &lt;= i &lt;= 0x10ffff.</code></pre>
<p><strong>Type:</strong> builtin_function_or_method</p>
</div>
</div>
<div id="b9dc643a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb19" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb19-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">''</span>.join(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">chr</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>(v, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>)) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> v <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> wrap(h, width<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="72">
<pre data-code-line-numbers=""><code>'This is some data'</code></pre>
</div>
</div>
<p>Or as ASCII encoding.</p>
<div id="36d0a0cf" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb21" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb21-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(buf.getvalue())</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="54">
<pre data-code-line-numbers=""><code>[84, 104, 105, 115, 32, 105, 115, 32, 115, 111, 109, 101, 32, 100, 97, 116, 97]</code></pre>
</div>
</div>
<div id="73e040dd" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb23" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb23-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">''</span>.join(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">chr</span>(v) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> v <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> buf.getvalue())</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="71">
<pre data-code-line-numbers=""><code>'This is some data'</code></pre>
</div>
</div>
<p>Hex escape format.</p>
<div id="67adda5b" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb25" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb25-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">''</span>.join(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">x</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>b<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:02x}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> b <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> buf.getvalue())</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="36">
<pre data-code-line-numbers=""><code>'\\x54\\x68\\x69\\x73\\x20\\x69\\x73\\x20\\x73\\x6f\\x6d\\x65\\x20\\x64\\x61\\x74\\x61'</code></pre>
</div>
</div>
<p>Or binary, how it’s actually stored in memory.</p>
<div id="54c6aa2a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb27" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb27-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bin</span>(buf.getvalue()[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="74">
<pre data-code-line-numbers=""><code>'0b1010100'</code></pre>
</div>
</div>
<div id="3a64f524" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb29" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb29-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">''</span>.join(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bin</span>(v) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> v <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> buf.getvalue())</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="77">
<pre data-code-line-numbers=""><code>'0b10101000b11010000b11010010b11100110b1000000b11010010b11100110b1000000b11100110b11011110b11011010b11001010b1000000b11001000b11000010b11101000b1100001'</code></pre>
</div>
</div>
<div id="49eaf47d" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb31" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb31-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">b'text'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'text'</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="17">
<pre data-code-line-numbers=""><code>(bytes, str)</code></pre>
</div>
</div>
<p>Apart from <code>.getvalue()</code>, we can also treat buffer as a list with a pointer, and read the contents being pointed at onward.</p>
<div id="0de963aa" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb33" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb33-1">buf.read()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="79">
<pre data-code-line-numbers=""><code>b''</code></pre>
</div>
</div>
<p>An empty string was returned. This is because the pointer is currently at the end of the list. We can seek back to the beginning of the list.</p>
<div id="32fc67f8" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb35" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb35-1">buf.seek(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="84">
<pre data-code-line-numbers=""><code>0</code></pre>
</div>
</div>
<div id="18087c96" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb37" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb37-1">buf.read()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="85">
<pre data-code-line-numbers=""><code>b'This is some data'</code></pre>
</div>
</div>
<div id="4463b6c7" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb39" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb39-1">buf.read()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="86">
<pre data-code-line-numbers=""><code>b''</code></pre>
</div>
</div>
<p>Let’s seek to the fourth byte.</p>
<div id="99149025" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb41" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb41-1">buf.seek(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)</span>
<span id="cb41-2">buf.read()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="87">
<pre data-code-line-numbers=""><code>b' is some data'</code></pre>
</div>
</div>
<p>We can see that the fifth byte is indeed blank space.</p>
<div id="e272528a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb43" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb43-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">chr</span>, buf.getvalue()))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="89">
<pre data-code-line-numbers=""><code>['T',
 'h',
 'i',
 's',
 ' ',
 'i',
 's',
 ' ',
 's',
 'o',
 'm',
 'e',
 ' ',
 'd',
 'a',
 't',
 'a']</code></pre>
</div>
</div>
<hr>
<p>If you have any comments, questions, suggestions, feedback, criticisms, or corrections, please do post them down in the comment section below!</p>



<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Programming</category>
  <category>Python</category>
  <guid>https://forbo7.github.io/forblog/posts/34_working_with_bytes.html</guid>
  <pubDate>Mon, 06 Apr 2026 00:00:00 GMT</pubDate>
  <media:content url="https://forbo7.github.io/forblog/images/34_working_with_bytes/thumbnail.png" medium="image" type="image/png" height="81" width="144"/>
</item>
<item>
  <title>Tunneling from SolveIt to your Machine</title>
  <dc:creator>Salman Naqvi</dc:creator>
  <link>https://forbo7.github.io/forblog/posts/33_tunneling_from_solveit_to_your_machine.html</link>
  <description><![CDATA[ 




<p><img src="https://forbo7.github.io/forblog/images/33_tunneling_from_solveit_to_your_machine/thumbnail.png" class="img-fluid"></p>
<div class="callout callout-style-simple callout-note">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>This post notes down what was originally taught by Jeremy Howard in Lesson 7 of the <a href="solve.it.com">SolveIt course</a> course led by <a href="https://solve.it.com/#im-jeremy-howard-from-fastai">Jeremy Howard</a> who created the first modern LLM in 2018, and <a href="https://www.johnowhitaker.com/">Johnothan Whitaker</a>. SolveIt is also a brilliant problem-solving framework and interactive platform, that puts you in control–not the LLM.</p>
<p>Also thanks to <a href="https://www.ekzhang.com/">Erik Zhang</a> for his super simple to use <a href="https://github.com/ekzhang/bore">Bore</a> library that makes it <em>really</em> easy to setup a tunnel between two computers.</p>
</div>
</div>
</div>
<p>This post details how one can provide SolveIt access to your local machine, thereby giving the LLM in SolveIt the context of your computer. Whilst the post focuses on macOS, the logic can be applied to other systems.</p>
<p>This post walks through setting up the connection via <a href="https://github.com/ekzhang/bore">Bore</a> by <a href="https://www.ekzhang.com/">Erik Zhang</a>, then wrapping it in a simple function that either you can use, or that can be used as an LLM tool.</p>
<p><strong>What you’ll need to do:</strong></p>
<ol type="1">
<li>Generate an SSH key on SolveIt</li>
<li>Enable remote access on your Mac and add the public key</li>
<li>Install <code>bore-cli</code> and <code>tmux</code> on your Mac</li>
<li>Start a Bore tunnel exposing port 22</li>
<li>Test the connection from SolveIt</li>
<li>(Optional) Create a tool function for LLM use</li>
</ol>
<section id="on-solveit" class="level2">
<h2 class="anchored" data-anchor-id="on-solveit">On SolveIt</h2>
<p>We need to first setup SSH Key Authentication. On the SolveIt instance, generate a new SSH key and note/copy the public key.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ssh-keygen</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-t</span> ed25519</span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cat</span> ~/.ssh/id_ed25519.pub</span></code></pre></div></div>
<p><code>-t ed25519</code> generates a key using the <code>ed25519</code> algorithm. This is supposedly safer, quicker, and a more concise alternative to the traditional RSA algorithm.</p>
</section>
<section id="on-your-machine" class="level2">
<h2 class="anchored" data-anchor-id="on-your-machine">On Your Machine</h2>
<p>First ensure that remote access is enabled in System Settings on your local machine.</p>
<p><img src="https://forbo7.github.io/forblog/images/33_tunneling_from_solveit_to_your_machine/1.png" class="img-fluid"></p>
<p>Next, install <code>bore-cli</code>. If you haven’t, also install <code>tmux</code> as it helps keep SSH connections persistent.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb2-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">brew</span> install bore-cli</span>
<span id="cb2-2"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">brew</span> install tmux</span></code></pre></div></div>
<p>Then, start a new tmux session. Here, I’ve called the session <code>bore</code>.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb3-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">tmux</span> new <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-s</span> bore</span></code></pre></div></div>
<p>Take the public key you generated on SolveIt. Then, on the local machine, add it to the list of authorized keys.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb4-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">echo</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"YOUR_PUBLIC_KEY_HERE"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;&gt;</span> ~/.ssh/authorized_keys</span></code></pre></div></div>
<p>Now it’s time to run bore. Note down the port that bore returns.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb5-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">bore</span> local 22 <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">--to</span> bore.pub</span></code></pre></div></div>
<p>This command exposes port 22 on your local machine to the bore public servers through an encrypted tunnel. Why 22? Because that is the default port macOS uses for SSH after enabling remote access. The port you get back is the port bore randomly allocates on its public servers.</p>
</section>
<section id="testing-the-connection-from-solveit" class="level2">
<h2 class="anchored" data-anchor-id="testing-the-connection-from-solveit">Testing the Connection from SolveIt</h2>
<p>And that should be it! Test the connection from SolveIt:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb6" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb6-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ssh</span> <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-o</span> StrictHostKeyChecking=no YOUR_USERNAME@bore.pub <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">-p</span> YOUR_PORT <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"echo Connection successful!"</span></span></code></pre></div></div>
<p>If you are running this command outside a Jupyter Notebook or a SolveIt Dialog, you can omit the <code>-o StrictHostKeyChecking=no</code> parameter. This parameter allows us to bypass the prompt that asks us to verify the connection.</p>
<p>fastcore has a <code>run_cmd</code> function we can use to abstract how we run commands. We could also use it to produce a tool the LLM can use.</p>
<div id="c0610c88" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fastcore.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">all</span> <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span></span>
<span id="cb7-2">?run_cmd</span></code></pre></div></div>
<div class="cell-output cell-output-display cell-output-markdown">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb8" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> run_cmd(</span>
<span id="cb8-2">    cmd:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># The command name to run</span></span>
<span id="cb8-3">    argstr:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># All args to the command, will be split with shlex</span></span>
<span id="cb8-4">    disallow_re:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># optional regex which, if matched on argstr, will disallow the command</span></span>
<span id="cb8-5">    allow_re:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># optional regex which, if not matched on argstr, will disallow the command</span></span>
<span id="cb8-6">):</span></code></pre></div></div>
<pre data-code-line-numbers=""><code>Run `cmd` passing split `argstr`, optionally checking for allowed argstr</code></pre>
<p><strong>File:</strong> <code>/usr/local/lib/python3.12/site-packages/fastcore/tools.py</code></p>
<p><strong>Type:</strong> function</p>
</div>
</div>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb10" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode py code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> mac(cmd:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, port:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>): </span>
<span id="cb10-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"Execute bash commands on the user's local Mac."</span></span>
<span id="cb10-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(run_cmd(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'ssh'</span>, <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'YOUR_USERNAME@bore.pub -p </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>port<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>cmd<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>))</span></code></pre></div></div>
<p>Now you’re able to control your local machine directly from SolveIt. You could also pass it as a tool to the LLM with <code>&amp;`mac`</code>.</p>
<hr>
<p>If you have any comments, questions, suggestions, feedback, criticisms, or corrections, please do post them down in the comment section below!</p>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>LLMs</category>
  <category>Agents</category>
  <category>SolveIt</category>
  <category>Shell</category>
  <guid>https://forbo7.github.io/forblog/posts/33_tunneling_from_solveit_to_your_machine.html</guid>
  <pubDate>Tue, 27 Jan 2026 00:00:00 GMT</pubDate>
  <media:content url="https://forbo7.github.io/forblog/images/33_tunneling_from_solveit_to_your_machine/thumbnail.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>Ways to Pull Repos into LLM Context</title>
  <dc:creator>Salman Naqvi</dc:creator>
  <link>https://forbo7.github.io/forblog/posts/32_ways_to_pull_repos_into_LLM_context.html</link>
  <description><![CDATA[ 




<p><img src="https://forbo7.github.io/forblog/images/32_ways_to_pull_repos_into_LLM_context/thumbnail.png" class="img-fluid"></p>
<p>Good context is key when working with LLMs, no matter if you’re coding, writing, planning, problem solving, and what not. The LLM needs to know your context to you help you effectively.</p>
<p>This guide will explore different ways one can pull a GitHub repo or a local repo in particular into a format LLMs can use.</p>
<section id="githubq" class="level2">
<h2 class="anchored" data-anchor-id="githubq">GitHubq</h2>
<p>GitHubq is a web service from <a href="https://www.answer.ai/">Answer.Ai</a> that allows you to easily make GitHub repos available as context for LLMs. The basic way to use the service is to change <code>github.com</code> to <code>githubq.com</code>.</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://forbo7.github.io/forblog/images/32_ways_to_pull_repos_into_LLM_context/1.png" class="img-fluid figure-img"></p>
<figcaption>Viewing the Shell Sage GitHub repo as LLM context</figcaption>
</figure>
</div>
<p>You can change what you get back with various parameters. For instance,</p>
<ul>
<li><code>exts=py</code> returns only files ending with <code>.py</code></li>
<li><code>sigs_only=True</code> returns only function signatures and their docstrings.</li>
</ul>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://forbo7.github.io/forblog/images/32_ways_to_pull_repos_into_LLM_context/2.png" class="img-fluid figure-img"></p>
<figcaption>Only Python files with function signatures are visible</figcaption>
</figure>
</div>
</section>
<section id="toolslm.xml" class="level2">
<h2 class="anchored" data-anchor-id="toolslm.xml"><code>toolslm.xml</code></h2>
<p>See the full documentation of Answer.AI’s <code>toolslm</code> library <a href="https://answerdotai.github.io/toolslm/">here</a>.</p>
<section id="repo2ctx" class="level3">
<h3 class="anchored" data-anchor-id="repo2ctx"><code>repo2ctx</code></h3>
<p>Githubq is great if you want to paste a link to a LLM that will then retrieve what’s on the link, or if you want to save one-off files here and there. What if you want to programmatically work with the context? That’s where <code>toolslm</code>, and more specifically the <code>toolslm.xml</code> module comes in.</p>
<div id="5bddf20f" class="cell" data-time_run="2026-01-17T02:42:20.228964+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> toolslm.xml <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> repo2ctx</span>
<span id="cb1-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(repo2ctx(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'https://github.com/AnswerDotAI/shell_sage'</span>, exts<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'py'</span>)[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>])</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>&lt;documents title="GitHub repository contents from AnswerDotAI/shell_sage/main (filters applied -- ex</code></pre>
</div>
</div>
<p>Behind the scenes, GitHubq uses <code>repo2ctx</code>. So parameters from <code>repo2ctx</code> should work as query parameters when accessing <code>GitHubq</code>.</p>
<div id="8f5d8fcb" class="cell" data-time_run="2026-01-17T02:43:21.673991+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1">?repo2ctx</span></code></pre></div></div>
<div class="cell-output cell-output-display cell-output-markdown">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> repo2ctx(</span>
<span id="cb4-2">    owner:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># GitHub repo owner or "owner/repo" or a full github URL</span></span>
<span id="cb4-3">    repo:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># GitHub repo name (leave empty if using "owner/repo" or URL format for owner param)</span></span>
<span id="cb4-4">    ref:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Git ref (branch/tag/sha) (get from URL not provided); defaults to repo's default branch</span></span>
<span id="cb4-5">    folder:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Only include files under this path (get from URL not provided)</span></span>
<span id="cb4-6">    show_filters:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Include filter info in title?</span></span>
<span id="cb4-7">    token:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># GitHub token (uses GITHUB_TOKEN env var if None)</span></span>
<span id="cb4-8">    prefix:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Include Anthropic's suggested prose intro?</span></span>
<span id="cb4-9">    out:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Include notebook cell outputs?</span></span>
<span id="cb4-10">    include_base:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Include full path in src?</span></span>
<span id="cb4-11">    title:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Optional title attr for Documents element</span></span>
<span id="cb4-12">    max_size:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100000</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Skip files larger than this (bytes)</span></span>
<span id="cb4-13">    max_total:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10000000</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Max total output size in bytes</span></span>
<span id="cb4-14">    readme_first:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Prioritize README files at start of context?</span></span>
<span id="cb4-15">    files_only:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Return dict of {filename: size} instead of context?</span></span>
<span id="cb4-16">    sigs_only:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Return signatures instead of full text for python files?</span></span>
<span id="cb4-17">    ids:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Include cell ids in notebooks?</span></span>
<span id="cb4-18">    recursive:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># search subfolders</span></span>
<span id="cb4-19">    symlinks:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># follow symlinks?</span></span>
<span id="cb4-20">    file_glob:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Only include files matching glob</span></span>
<span id="cb4-21">    file_re:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Only include files matching regex</span></span>
<span id="cb4-22">    folder_re:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Only enter folders matching regex</span></span>
<span id="cb4-23">    skip_file_glob:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Skip files matching glob</span></span>
<span id="cb4-24">    skip_file_re:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Skip files matching regex</span></span>
<span id="cb4-25">    skip_folder_re:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Skip folders matching regex,</span></span>
<span id="cb4-26">    ret_folders:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># return folders, not just files</span></span>
<span id="cb4-27">    sort:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># sort files by name within each folder</span></span>
<span id="cb4-28">    types:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> \<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># list or comma-separated str of ext types from: py, js, java, c, cpp, rb, r, ex, sh, web, doc, cfg</span></span>
<span id="cb4-29">    exts:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> \<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># list or comma-separated str of exts to include</span></span>
<span id="cb4-30">)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span>Union: <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># XML for LM context, or dict of file sizes</span></span></code></pre></div></div>
<pre data-code-line-numbers=""><code>Convert GitHub repo to XML context without cloning</code></pre>
<p><strong>File:</strong> <code>~/.local/lib/python3.12/site-packages/toolslm/xml.py</code></p>
<p><strong>Type:</strong> function</p>
</div>
</div>
<div id="4a00baa8" class="cell" data-time_run="2026-01-17T02:44:11.205004+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>ls </span></code></pre></div></div>
<div class="cell-output cell-output-display cell-output-markdown">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb7" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> folder2ctx(</span>
<span id="cb7-2">    path:Union, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Folder to read</span></span>
<span id="cb7-3">    prefix:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Include Anthropic's suggested prose intro?</span></span>
<span id="cb7-4">    out:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Include notebook cell outputs?</span></span>
<span id="cb7-5">    include_base:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Include full path in src?</span></span>
<span id="cb7-6">    title:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Optional title attr for Documents element</span></span>
<span id="cb7-7">    max_size:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100000</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Skip files larger than this (bytes)</span></span>
<span id="cb7-8">    max_total:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10000000</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Max total output size in bytes</span></span>
<span id="cb7-9">    readme_first:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Prioritize README files at start of context?</span></span>
<span id="cb7-10">    files_only:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Return dict of {filename: size} instead of context?</span></span>
<span id="cb7-11">    sigs_only:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Return signatures instead of full text for python files?</span></span>
<span id="cb7-12">    ids:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Include cell ids in notebooks?</span></span>
<span id="cb7-13">    recursive:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># search subfolders</span></span>
<span id="cb7-14">    symlinks:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># follow symlinks?</span></span>
<span id="cb7-15">    file_glob:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Only include files matching glob</span></span>
<span id="cb7-16">    file_re:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Only include files matching regex</span></span>
<span id="cb7-17">    folder_re:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Only enter folders matching regex</span></span>
<span id="cb7-18">    skip_file_glob:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Skip files matching glob</span></span>
<span id="cb7-19">    skip_file_re:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Skip files matching regex</span></span>
<span id="cb7-20">    skip_folder_re:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Skip folders matching regex,</span></span>
<span id="cb7-21">    ret_folders:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># return folders, not just files</span></span>
<span id="cb7-22">    sort:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># sort files by name within each folder</span></span>
<span id="cb7-23">    types:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> \<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># list or comma-separated str of ext types from: py, js, java, c, cpp, rb, r, ex, sh, web, doc, cfg</span></span>
<span id="cb7-24">    exts:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> \<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># list or comma-separated str of exts to include</span></span>
<span id="cb7-25">)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span>Union:</span></code></pre></div></div>
<pre data-code-line-numbers=""><code>Convert folder contents to XML context, handling notebooks</code></pre>
<p><strong>File:</strong> <code>~/.local/lib/python3.12/site-packages/toolslm/xml.py</code></p>
<p><strong>Type:</strong> function</p>
</div>
</div>
</section>
<section id="folder2ctx" class="level3">
<h3 class="anchored" data-anchor-id="folder2ctx"><code>folder2ctx</code></h3>
<p>Now this is great for remote repositories. If you have a local folder, you can turn that into context with <code>folder2ctx</code>.</p>
<div id="d324925f" class="cell" data-time_run="2026-01-17T02:45:39.304580+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>ls</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>'00-09 系统'   70ec03a05ceeffe770a8d00297fa241a   solveit_settings.json
'20-29 大学'   jobs.csv                 test
'30–39 学习'   shell_sage           暂时对话</code></pre>
</div>
</div>
<div id="c857f4bc" class="cell" data-time_run="2026-01-17T02:45:26.293637+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> toolslm.xml <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> folder2ctx</span>
<span id="cb11-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(folder2ctx(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'shell_sage'</span>, exts<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'py'</span>)[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">250</span>])</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>&lt;documents&gt;&lt;document index="1"&gt;&lt;src&gt;
shell_sage/setup.py
&lt;/src&gt;&lt;document-content&gt;
from pkg_resources import parse_version
from configparser import ConfigParser
import setuptools, shlex
assert parse_version(setuptools.__version__)&gt;=parse_version('36.2</code></pre>
</div>
</div>
</section>
<section id="py2sigs" class="level3">
<h3 class="anchored" data-anchor-id="py2sigs"><code>py2sigs</code></h3>
<p><code>py2sigs</code> can let us directly get function signature from a given Python file.</p>
<div id="3ff06d87" class="cell" data-time_run="2026-01-17T02:46:58.144939+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> toolslm.xml <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> py2sigs</span>
<span id="cb13-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(py2sigs(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'shell_sage/shell_sage/core.py'</span>)[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">250</span>])</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>def __rich_console__(self:CodeBlock, console, options):

def Chat(*arg, **kw):
    "Lazy load lisette to make ssage more responsive"

def _aliases(shell):

def _sys_info():

def get_pane(n, pid=None):
    "Get output from a tmux pane"

def get_panes(</code></pre>
</div>
</div>
</section>
<section id="sym2pkgctx" class="level3">
<h3 class="anchored" data-anchor-id="sym2pkgctx"><code>sym2pkgctx</code></h3>
<p>If you have a package already installed, you can use <code>toolslm</code>’s <code>sym2pkgctx</code> to pull that package in as context. The entire root package is returned.</p>
<div id="38123c07" class="cell" data-time_run="2026-01-17T02:58:14.248533+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb15" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb15-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(sym2pkgctx(sc.ShellSageConfig)[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">250</span>])</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>&lt;documents&gt;&lt;document index="1"&gt;&lt;src&gt;
/usr/local/lib/python3.12/site-packages/shell_sage/__init__.py
&lt;/src&gt;&lt;document-content&gt;
__version__ = "1.0.4"
&lt;/document-content&gt;&lt;/document&gt;&lt;document index="2"&gt;&lt;src&gt;
/usr/local/lib/python3.12/site-packages/shell_s</code></pre>
</div>
</div>
</section>
<section id="sym2folderctx" class="level3">
<h3 class="anchored" data-anchor-id="sym2folderctx"><code>sym2folderctx</code></h3>
<p><code>sym2folderctx</code> is similar to <code>sym2pkgctx</code>. However, the difference is that the former returns the returns the context of the folder where the symbol is defined.</p>
<div id="c290df66" class="cell" data-time_run="2026-01-19T00:22:44.367952+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb17" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb17-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> toolslm.xml <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> sym2folderctx</span>
<span id="cb17-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(sym2folderctx(sc.ShellSageConfig)[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">250</span>])</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>&lt;documents&gt;&lt;document index="1"&gt;&lt;src&gt;
/usr/local/lib/python3.12/site-packages/shell_sage/__init__.py
&lt;/src&gt;&lt;document-content&gt;
__version__ = "1.0.4"
&lt;/document-content&gt;&lt;/document&gt;&lt;document index="2"&gt;&lt;src&gt;
/usr/local/lib/python3.12/site-packages/shell_s</code></pre>
</div>
</div>
<div id="49e809c4" class="cell" data-time_run="2026-01-19T00:22:54.443764+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb19" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb19-1">?sym2pkgctx</span></code></pre></div></div>
<div class="cell-output cell-output-display cell-output-markdown">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb20" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb20-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> sym2pkgctx(</span>
<span id="cb20-2">    sym,</span>
<span id="cb20-3">    types:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> \<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'py'</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># list or comma-separated str of ext types from: py, js, java, c, cpp, rb, r, ex, sh, web, doc, cfg</span></span>
<span id="cb20-4">    skip_file_re:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'^_mod'</span>, prefix:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Include Anthropic's suggested prose intro?</span></span>
<span id="cb20-5">    out:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Include notebook cell outputs?</span></span>
<span id="cb20-6">    include_base:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Include full path in src?</span></span>
<span id="cb20-7">    title:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Optional title attr for Documents element</span></span>
<span id="cb20-8">    max_size:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100000</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Skip files larger than this (bytes)</span></span>
<span id="cb20-9">    max_total:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10000000</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Max total output size in bytes</span></span>
<span id="cb20-10">    readme_first:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Prioritize README files at start of context?</span></span>
<span id="cb20-11">    files_only:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Return dict of {filename: size} instead of context?</span></span>
<span id="cb20-12">    sigs_only:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Return signatures instead of full text for python files?</span></span>
<span id="cb20-13">    ids:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Include cell ids in notebooks?</span></span>
<span id="cb20-14">    recursive:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># search subfolders</span></span>
<span id="cb20-15">    symlinks:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># follow symlinks?</span></span>
<span id="cb20-16">    file_glob:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Only include files matching glob</span></span>
<span id="cb20-17">    file_re:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Only include files matching regex</span></span>
<span id="cb20-18">    folder_re:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Only enter folders matching regex</span></span>
<span id="cb20-19">    skip_file_glob:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Skip files matching glob</span></span>
<span id="cb20-20">    skip_folder_re:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Skip folders matching regex,</span></span>
<span id="cb20-21">    ret_folders:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># return folders, not just files</span></span>
<span id="cb20-22">    sort:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">bool</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># sort files by name within each folder</span></span>
<span id="cb20-23">    exts:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span> \<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># list or comma-separated str of exts to include</span></span>
<span id="cb20-24">):</span></code></pre></div></div>
<pre data-code-line-numbers=""><code>Return repo context for a symbol's root package</code></pre>
<p><strong>File:</strong> <code>~/.local/lib/python3.12/site-packages/toolslm/xml.py</code></p>
<p><strong>Type:</strong> function</p>
</div>
</div>
</section>
</section>
<section id="contextkit" class="level2">
<h2 class="anchored" data-anchor-id="contextkit"><code>contextkit</code></h2>
<p>Next up is <code>contextkit</code>’s <code>read</code> module. However, this approach is much more hands on as the module’s functions do not return XML formatted contents. Though this does allow you to perform your own processing/handling. You will need to have a SSH key set up between your machine and GitHub as the functions in <code>read</code> create temporary clones of the GitHub repo.</p>
<p><code>contextkit.read</code>s <code>read_gh_repo</code> returns a dictionary in the format of <code>{'path': 'contents'}</code>.</p>
<div id="49216ec4" class="cell" data-time_run="2026-01-17T02:55:40.914215+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb22" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb22-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> contextkit.read <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> rd</span>
<span id="cb22-2">rd.read_gh_repo(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'https://github.com/AnswerDotAI/shell_sage'</span>).keys()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>dict_keys(['/app/data/.cache/contextkit_git_clones/shell_sage/settings.ini', '/app/data/.cache/contextkit_git_clones/shell_sage/CONTRIBUTING.md', '/app/data/.cache/contextkit_git_clones/shell_sage/LICENSE', '/app/data/.cache/contextkit_git_clones/shell_sage/README.md', '/app/data/.cache/contextkit_git_clones/shell_sage/pyproject.toml', '/app/data/.cache/contextkit_git_clones/shell_sage/uv.lock', '/app/data/.cache/contextkit_git_clones/shell_sage/MANIFEST.in', '/app/data/.cache/contextkit_git_clones/shell_sage/setup.py', '/app/data/.cache/contextkit_git_clones/shell_sage/CHANGELOG.md', '/app/data/.cache/contextkit_git_clones/shell_sage/ipython/00-init.py', '/app/data/.cache/contextkit_git_clones/shell_sage/nbs/_quarto.yml', '/app/data/.cache/contextkit_git_clones/shell_sage/nbs/CNAME', '/app/data/.cache/contextkit_git_clones/shell_sage/nbs/sidebar.yml', '/app/data/.cache/contextkit_git_clones/shell_sage/nbs/tmux.conf', '/app/data/.cache/contextkit_git_clones/shell_sage/nbs/01_config.ipynb', '/app/data/.cache/contextkit_git_clones/shell_sage/nbs/00_core.ipynb', '/app/data/.cache/contextkit_git_clones/shell_sage/nbs/styles.css', '/app/data/.cache/contextkit_git_clones/shell_sage/nbs/index.ipynb', '/app/data/.cache/contextkit_git_clones/shell_sage/nbs/nbdev.yml', '/app/data/.cache/contextkit_git_clones/shell_sage/shell_sage/core.py', '/app/data/.cache/contextkit_git_clones/shell_sage/shell_sage/__init__.py', '/app/data/.cache/contextkit_git_clones/shell_sage/shell_sage/_modidx.py', '/app/data/.cache/contextkit_git_clones/shell_sage/shell_sage/config.py', '/app/data/.cache/contextkit_git_clones/shell_sage/debug/aliases.py', '/app/data/.cache/contextkit_git_clones/shell_sage/debug/safe_aliases.py', '/app/data/.cache/contextkit_git_clones/shell_sage/debug/probe_tty.py'])</code></pre>
</div>
</div>
<p><code>read_gh_file</code> returns the contents of the file as a string.</p>
<div id="4163bbb4" class="cell" data-time_run="2026-01-17T02:55:54.029355+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb24" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb24-1">rd.read_gh_file(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'https://github.com/AnswerDotAI/shell_sage/blob/main/shell_sage/core.py'</span>)[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">250</span>]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>"# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/00_core.ipynb.\n\n# %% auto 0\n__all__ = ['console', 'print', 'sp', 'ssp', 'default_cfg', 'tools', 'sps', 'log_path', 'Chat', 'get_pane', 'get_panes',\n           'tmux_history_lim', 'get_history', 'get_"</code></pre>
</div>
</div>
<div id="6072f3bf" class="cell" data-time_run="2026-01-17T02:55:26.009402+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb26" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb26-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(rd.read_gh_file(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'https://github.com/AnswerDotAI/shell_sage/blob/main/shell_sage/core.py'</span>)[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">250</span>])</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code># AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/00_core.ipynb.

# %% auto 0
__all__ = ['console', 'print', 'sp', 'ssp', 'default_cfg', 'tools', 'sps', 'log_path', 'Chat', 'get_pane', 'get_panes',
           'tmux_history_lim', 'get_history', 'get_</code></pre>
</div>
</div>
<p>See the full documentation of Answer.AI’s <code>contextkit</code> library <a href="https://github.com/AnswerDotAI/contextkit">here</a>.</p>
</section>
<section id="solveit" class="level2">
<h2 class="anchored" data-anchor-id="solveit">SolveIt</h2>
<p>If you’re in SolveIt, you can also change directory and ask the LLM to directly read through a particular directory for you with its builtin tools. Note that you should use <code>%</code> rather than <code>!</code> so the directory switches in a non-temporary manner.</p>
<div id="13933d07" class="cell" data-time_run="2026-01-17T02:59:23.582168+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb28" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb28-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>cd shell_sage</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>/app/data/shell_sage</code></pre>
</div>
</div>
<hr>
<p>Can you look through the directory and tell me what are the key functions of the shell sage library?</p>
<section id="reply" class="level5">
<h5 class="anchored" data-anchor-id="reply">🤖Reply🤖<!-- SOLVEIT_SEPARATOR_7f3a9b2c --></h5>
<p>🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠</p>
<p>让我看看这个目录的结构：</p>
<details class="tool-usage-details">
<summary>
view(path=.)
</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb30" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode json code-with-copy"><code class="sourceCode json"><span id="cb30-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb30-2">  <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"id"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"toolu_01TcJme7ugD8Xzq3rBZLjinR"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb30-3">  <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"call"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb30-4">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"function"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"view"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb30-5">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"arguments"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb30-6">      <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"path"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"."</span></span>
<span id="cb30-7">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb30-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">},</span></span>
<span id="cb30-9">  <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"result"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"'Directory contents of /app/&lt;TRUNCATED&gt;"</span></span>
<span id="cb30-10"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div></div>
</details>
<p>主要代码在 <code>shell_sage/</code> 文件夹里。让我看看 <code>core.py</code> 的签名：</p>
<details class="tool-usage-details">
<summary>
view(path=shell_sage/core.py, view_range=[1, 50])
</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb31" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode json code-with-copy"><code class="sourceCode json"><span id="cb31-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb31-2">  <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"id"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"toolu_01N9i48X1GWBFrBj9awo8qzk"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb31-3">  <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"call"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb31-4">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"function"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"view"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb31-5">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"arguments"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb31-6">      <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"path"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"shell_sage/core.py"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb31-7">      <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"view_range"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"[1, 50]"</span></span>
<span id="cb31-8">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb31-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">},</span></span>
<span id="cb31-10">  <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"result"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"'# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/00_core.ipynb.</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n# %% auto 0</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n__all__ = [</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'console</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">', </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'print</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">', </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sp</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">', </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'ssp</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">', </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'default_cfg</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">', </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tools</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">', </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'sps</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">', </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'log_path</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">', </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Chat</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">', </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'get_pane</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">', </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'get_panes</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">',</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n           </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tmux_history_lim</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">', </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'get_history</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">', </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'get_opts</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">', </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'with_permission</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">', </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'get_sage</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">', </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'get_res</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">', </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Log</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">', </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mk_db</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">',</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n           </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'main</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">', </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'extract_cf</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">', </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'extract</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">']</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n# %% ../nbs/00_core.ipynb 3</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">nfrom datetime import datetime</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">nfrom itertools import accumulate</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">nfrom fastcore.script import *</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">nfrom fastcore.tools import *</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">nfrom fastcore.utils import *</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">nfro&lt;TRUNCATED&gt;"</span></span>
<span id="cb31-11"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div></div>
</details>
<hr>
<p><strong>Shell Sage 的主要功能：</strong></p>
<p>根据 <code>__all__</code> 导出列表，关键函数包括：</p>
<table class="caption-top table">
<thead>
<tr class="header">
<th>函数</th>
<th>用途</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>main</code></td>
<td>主入口点（CLI 命令 <code>ssage</code>）</td>
</tr>
<tr class="even">
<td><code>get_pane</code>, <code>get_panes</code></td>
<td>获取 tmux 窗格信息</td>
</tr>
<tr class="odd">
<td><code>get_history</code></td>
<td>获取 tmux 历史记录</td>
</tr>
<tr class="even">
<td><code>get_sage</code></td>
<td>获取 AI 响应</td>
</tr>
<tr class="odd">
<td><code>Chat</code></td>
<td>延迟加载 LLM 聊天功能</td>
</tr>
<tr class="even">
<td><code>Log</code>, <code>mk_db</code></td>
<td>日志和数据库功能</td>
</tr>
<tr class="odd">
<td><code>extract</code>, <code>extract_cf</code></td>
<td>从响应中提取代码</td>
</tr>
</tbody>
</table>
<p>简单说：<strong>Shell Sage 是一个 AI 命令行助手，它能读取你的 tmux 终端历史，然后用 LLM 帮你解决 shell 问题。</strong></p>
<hr>
<p>You can of course also directly paste in a URL and the LLM will look through it.</p>
<hr>
<p>What’s this GitHub repo about? https://github.com/AnswerDotAI/shell_sage</p>
</section>
<section id="reply-1" class="level5">
<h5 class="anchored" data-anchor-id="reply-1">🤖Reply🤖<!-- SOLVEIT_SEPARATOR_7f3a9b2c --></h5>
<p>🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠</p>
<details class="tool-usage-details">
<summary>
read_url(url=https://github.com/AnswerDotAI/shell_sage)
</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb32" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode json code-with-copy"><code class="sourceCode json"><span id="cb32-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb32-2">  <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"id"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"toolu_011DD4XT7Yge4mwqi49s3u6Z"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb32-3">  <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"call"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb32-4">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"function"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"read_url"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb32-5">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"arguments"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">{</span></span>
<span id="cb32-6">      <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"url"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://github.com/AnswerDotAI/shell_sage"</span></span>
<span id="cb32-7">    <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span></span>
<span id="cb32-8">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">},</span></span>
<span id="cb32-9">  <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">"result"</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"'# AnswerDotAI/shell_sage</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">nShellSage saves sysadmins</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\u2019</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> sanity by solving shell script snafus super swiftly</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n## / Files</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n- </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\ud83d\udcc1</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> .github</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n- .gitignore</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n- CHANGELOG.md</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n- CONTRIBUTING.md</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n- LICENSE</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n- MANIFEST.in</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n- README.md</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n- </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\ud83d\udcc1</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> debug</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n- </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\ud83d\udcc1</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> ipython</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n- </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\ud83d\udcc1</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> nbs</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n- pyproject.toml</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n- </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\ud83d\udcc1</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> screenshots</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n- settings.ini</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n- setup.py</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n- </span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\ud83d\udcc1</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;"> shell_sage</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n- uv.lock</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n## README</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n# ShellSage</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n&lt;!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! --&gt;</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">n</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">nShellSage is an AI-powered command-line assistant that integrates</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">nseamlessly with your terminal workflow through tmux. It provides</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\\</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">ncontextual help for shell ope&lt;TRUNCATED&gt;"</span></span>
<span id="cb32-10"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">}</span></span></code></pre></div></div>
</details>
<p><strong>Shell Sage</strong> 是一个 AI 驱动的命令行助手，通过 tmux 集成到你的终端工作流中。</p>
<p><strong>主要特点：</strong> - 用 <code>ssage</code> 命令在终端里问问题 - 能自动读取 tmux 历史记录来提供上下文帮助 - 支持多种 LLM 提供商（Claude、GPT、Ollama 等） - 可以分析管道输入（piped input） - 有个有趣的 “sassy mode”（GLaDOS 风格的回复）</p>
<p><strong>安装：</strong></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb33" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb33-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">pip</span> install shell-sage</span></code></pre></div></div>
<hr>
</section>
</section>
<section id="at-an-overview" class="level2">
<h2 class="anchored" data-anchor-id="at-an-overview">At an Overview</h2>
<table class="caption-top table">
<colgroup>
<col style="width: 32%">
<col style="width: 28%">
<col style="width: 40%">
</colgroup>
<thead>
<tr class="header">
<th>Method</th>
<th>Input</th>
<th>Best For</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong><code>githubq</code></strong></td>
<td>Change URL to githubq.com</td>
<td>Quick browser-based access</td>
</tr>
<tr class="even">
<td><strong><code>repo2ctx</code></strong></td>
<td>GitHub URL</td>
<td>Programmatic access to remote repos</td>
</tr>
<tr class="odd">
<td><strong><code>folder2ctx</code></strong></td>
<td>Local path</td>
<td>Processing local folders</td>
</tr>
<tr class="even">
<td><strong><code>py2sigs</code></strong></td>
<td>Python file path</td>
<td>Single file signatures</td>
</tr>
<tr class="odd">
<td><strong><code>contextkit.read_gh_repo</code></strong></td>
<td>GitHub URL</td>
<td>Raw dict of full repo contents</td>
</tr>
<tr class="even">
<td><strong><code>contextkit.read_gh_file</code></strong></td>
<td>File URL</td>
<td>Single file contents</td>
</tr>
<tr class="odd">
<td><strong><code>sym2pkgctx</code></strong></td>
<td>Class/function object</td>
<td>Installed packages</td>
</tr>
<tr class="even">
<td><strong><code>sym2folderctx</code></strong></td>
<td>Class/function object</td>
<td>Folder containing a symbol</td>
</tr>
<tr class="odd">
<td><strong><code>read_url</code></strong> (SolveIt)</td>
<td>GitHub URL</td>
<td>Quick repo overview + README</td>
</tr>
</tbody>
</table>
</section>
<section id="other-toolslm.xml-goodies" class="level2">
<h2 class="anchored" data-anchor-id="other-toolslm.xml-goodies">Other <code>toolslm.xml</code> Goodies</h2>
<p>Beyond the functions we’ve covered, <code>toolslm.xml</code> has other interesting functions:</p>
<p><strong>Additional Functions:</strong> - <code>files2ctx</code> — Pass in a specific list of files rather than an entire folder - <code>nb2xml</code> — Convert Jupyter notebooks to XML format - <code>json_to_xml</code> — Convert JSON or Python dicts to XML - <code>sym2file</code> — Get the source file contents for any class or function</p>
<p><strong>Useful Parameters:</strong> - <code>prefix=True</code> — Prepends Anthropic’s recommended preamble for document context - <code>nums=True</code> — Adds line numbers to code (handy for referencing specific lines)</p>
<p><strong>Command Line Support:</strong> Both <code>folder2ctx</code> and <code>repo2ctx</code> are available as CLI tools, so you can use them directly from your terminal without writing Python.</p>
<p>There’s plenty more to discover. Explore the full module at the <a href="https://answerdotai.github.io/toolslm/xml.html">docs</a> by pulling it into a LLM with the techniques we’ve learned here!</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>If you have any comments, questions, suggestions, feedback, criticisms, or corrections, please do post them down in the comment section below!</p>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>LLMs</category>
  <category>Agents</category>
  <category>SolveIt</category>
  <guid>https://forbo7.github.io/forblog/posts/32_ways_to_pull_repos_into_LLM_context.html</guid>
  <pubDate>Sun, 25 Jan 2026 00:00:00 GMT</pubDate>
  <media:content url="https://forbo7.github.io/forblog/images/32_ways_to_pull_repos_into_LLM_context/thumbnail.png" medium="image" type="image/png" height="81" width="144"/>
</item>
<item>
  <title>Building SolveIt in SolveIt</title>
  <dc:creator>Salman Naqvi</dc:creator>
  <link>https://forbo7.github.io/forblog/posts/31_solveit_in_solveit.html</link>
  <description><![CDATA[ 




<p><img src="https://forbo7.github.io/forblog/images/31_solveit_in_solveit/thumbnail.png" class="img-fluid"></p>
<div class="callout callout-style-simple callout-note">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>This app is built on the techniques taught in Lessons 4, 5, and 6 of the SolveIt course led by <a href="https://solve.it.com/#im-jeremy-howard-from-fastai">Jeremy Howard</a> who created the first modern LLM in 2018, and <a href="https://www.johnowhitaker.com/">Johnothan Whitaker</a>. SolveIt is also a brilliant problem-solving framework and interactive platform, that puts you in control–not the LLM.</p>
<p>Also thanks to <a href="https://rensdimmendaal.com/">Rens Dimmendaal</a> for <a href="https://share.solve.it.com/d/5426704f61ba89b1ae547d6506929da7">his dialog</a> on how to deploy an app to <a href="https://pla.sh/">Plash</a> from SolveIt.</p>
</div>
</div>
</div>
<p>This blog post is a rendered documentation of a very, very basic reimplementation of <a href="solve.it.com">SolveIt</a> using FastHTML as the web framework. The main goal of this exercise was to exercise my web development and HTMX skillz. Play with the app <a href="https://solveit-lite-unofficial.pla.sh/">at this link</a>. Or watch the brief overview below.</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0;">
<iframe src="https://cap.so/embed/k9xxnxzyfa19fms" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen="" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">
</iframe>
</div>
<p>SolveIt is an IDE of sorts that’s not only tailored towards coding, but a variety of other tasks from writing to problem solving to planning to learning to exploring and what not. Its premise revolves around the LLM putting the human in control, and thereby boosting human performance and capability. A core part of why SolveIt works so well is that your work <em>is</em> the LLM context.</p>
<p>Many parts of this app can still be improved, refactored, or made more efficient. Play with the app <a href="https://solveit-lite-unofficial.pla.sh/">at this link</a>.</p>
<p>Features include:</p>
<ul>
<li>Code/LLM/Note cells</li>
<li>Context aware LLM</li>
<li>Restore functionality</li>
<li>Create multiple dialogs</li>
<li>Rename dialogs</li>
<li>Chinese/English localization</li>
</ul>
<div class="callout callout-style-simple callout-note">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>Certain FastHTML components of my app have been directly rendered as a part of this page. The FastHTML routes have not been and have been displayed as an image–these would otherwise be rendered in a Jupyter Notebook.</p>
</div>
</div>
</div>
<section id="settings-and-headers" class="level3">
<h3 class="anchored" data-anchor-id="settings-and-headers">Settings and Headers</h3>
<p>::: {#243ffab3 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:33:56.461282+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fasthtml.common <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span></span></code></pre></div></div>
<p>:::</p>
<p>::: {#f9ccd095 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:33:56.462308+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1">bsc_hdrs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (</span>
<span id="cb2-2">    Script(src<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"</span>),  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Need to download first.</span></span>
<span id="cb2-3">    Link(rel<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'stylesheet'</span>, href<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css'</span>),</span>
<span id="cb2-4">    Script(src<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js'</span>, defer<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>),</span>
<span id="cb2-5">)</span></code></pre></div></div>
<p>:::</p>
<p>::: {#7d1e280a .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:33:56.482447+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1">app <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> FastHTML(hdrs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(bsc_hdrs, MarkdownJS(), HighlightJS(langs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'python'</span>])), session_cookie<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mysessioncookie'</span>, debug<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb3-2">rt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> app.route</span></code></pre></div></div>
<p>:::</p>
<p>A custom session cookie needs to be set for FastHTML sessions to work in SolveIt as SolveIt currently uses the default one.</p>
</section>
<section id="preview" class="level3">
<h3 class="anchored" data-anchor-id="preview">Preview</h3>
<p>Here I create a preview helper function that will allow me to interactively preview various components of the app.</p>
<div id="852a294e" class="cell" data-time_run="2026-01-22T00:33:56.519355+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> functools <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> partial</span>
<span id="cb4-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fasthtml.jupyter <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span></span></code></pre></div></div>
</div>
<div id="2f10b55b" class="cell" data-time_run="2026-01-22T00:33:56.544206+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1">server <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> JupyUvi(app)</span></code></pre></div></div>
</div>
<div id="7e804dcd" class="cell" data-time_run="2026-01-22T00:33:56.577126+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_preview(app):</span>
<span id="cb6-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> partial(HTMX, app<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>app, host<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, port<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>)</span>
<span id="cb6-3">prev <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_preview(app)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> prev()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe src="../../" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<div id="4d6427b8" class="cell" data-time_run="2026-01-22T00:33:56.607309+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1">render_ft()</span></code></pre></div></div>
</div>
<p><code>render_ft</code> will render any output FastHTML. <code>prev</code> will display it in the context of the FastHTML app.</p>
</section>
<section id="database" class="level3">
<h3 class="anchored" data-anchor-id="database">Database</h3>
<p>Creating a database to store users and their dialogs, with dialogs linked to users via <code>uid</code>.</p>
<p>::: {#1f39f676 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:33:56.637473+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fastlite <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span></span></code></pre></div></div>
<p>:::</p>
<p>::: {#88d6aa36 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:33:56.668265+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1">db <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> database(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'solvish.db'</span>)</span></code></pre></div></div>
<p>:::</p>
<div id="bfa6f9fd" class="cell" data-time_run="2026-01-22T00:33:56.699037+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1">db</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>&lt;Database &lt;apsw.Connection object "/app/data/forbo7.github.io/forblog/posts/solvish.db" at 0x70ee23760500&gt;&gt;</code></pre>
</div>
</div>
<p>::: {#dd112d66 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:33:57.092178+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> User: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span>:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> restore_code:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span></span>
<span id="cb12-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Dialog: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span>:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> uid:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> dialog_num:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> name:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> messages:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> server_session:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span></span></code></pre></div></div>
<p>:::</p>
<p>::: {#6bd3be8e .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:33:57.093191+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1">users <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> db.create(User, transform<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb13-2">dialogs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> db.create(Dialog, pk<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'uid'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'dialog_num'</span>), transform<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span></code></pre></div></div>
<p>:::</p>
<p>Tables will not be overwritten as <code>db.create()</code> is idempotent.</p>
<div id="3638ca94" class="cell" data-time_run="2026-01-22T00:33:57.124593+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1">users.delete_where()</span>
<span id="cb14-2">dialogs.delete_where()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>&lt;Table dialog (id, uid, dialog_num, name, messages, server_session)&gt;</code></pre>
</div>
</div>
<p><code>.delete_where</code> with no arguments passed will drop all rows from the table.</p>
</section>
<section id="new-dialog" class="level3">
<h3 class="anchored" data-anchor-id="new-dialog">New Dialog</h3>
<p>Creating a new dialog first auto-increments <code>dialog_num</code> based on the user’s existing dialogs, then sets <code>session['current_dialog']</code> to track which dialog is active. The dialog is stored in the <code>dialogs</code> table for persistence across sessions, while also being loaded into <code>user_chats</code> as a live chat object for the current server session.</p>
<p>::: {#b7b8f919 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:33:57.163073+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> lisette.core <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span></span>
<span id="cb16-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> toolslm.shell <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> get_shell</span>
<span id="cb16-3"></span>
<span id="cb16-4">sp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Respond in the language the user uses; The user has access to a Python interpreter that you can view; NEVER copy the format of the code interpreter messsages in your response.'</span></span>
<span id="cb16-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> make_chat(hist<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[]): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Chat(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'moonshot/kimi-k2-0711-preview'</span>, hist<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>hist, sp<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>sp), get_shell()</span></code></pre></div></div>
<p>:::</p>
<div id="1bfb32c4" class="cell" data-time_run="2026-01-22T00:33:58.698358+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb17" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb17-1">make_chat()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>(&lt;lisette.core.Chat at 0x70ee1a849eb0&gt;,
 &lt;IPython.terminal.interactiveshell.TerminalInteractiveShell at 0x70ee1a849f40&gt;)</code></pre>
</div>
</div>
<p>As my Kimi API key is compatable with servers in China, I have to change the Moonshoot endpoint.</p>
<p>::: {#35143833 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:33:58.702646+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb19" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb19-1">os.environ[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MOONSHOT_API_BASE'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'https://api.moonshot.cn/v1'</span></span></code></pre></div></div>
<p>:::</p>
<div id="7528bd96" class="cell" data-time_run="2026-01-22T00:33:58.706844+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb20" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb20-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># from cachy import enable_cachy; enable_cachy()</span></span></code></pre></div></div>
</div>
<p><a href="https://github.com/AnswerDotAI/cachy">cachy</a> will cache my API calls.</p>
<div id="bed3a9e7" class="cell" data-time_run="2026-01-22T00:33:58.730016+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb21" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb21-1">make_chat()[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>](<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'what do you have access to?'</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display cell-output-markdown" data-execution_count="0">
<p>I can see everything you see in the chat, including any code you run and its output. I don’t have direct access to your file system, network, or any other external resources—only what you explicitly show me in the conversation.</p>
<details>
<ul>
<li>id: <code>chatcmpl-6971707810ede230dafd4d84</code></li>
<li>model: <code>moonshot/kimi-k2-0711-preview</code></li>
<li>finish_reason: <code>stop</code></li>
<li>usage: <code>Usage(completion_tokens=49, prompt_tokens=54, total_tokens=103, completion_tokens_details=None, prompt_tokens_details=None)</code></li>
</ul>
</details>
</div>
</div>
<p>::: {#50efa44f .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:01.492003+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb22" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb22-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> coolname <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> generate_slug</span>
<span id="cb22-2"></span>
<span id="cb22-3"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb22-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> create_dialog(session):</span>
<span id="cb22-5">    uid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> session.get(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'userid'</span>)</span>
<span id="cb22-6">    existing <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dialogs(where<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'uid=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>uid<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>)</span>
<span id="cb22-7">    dnum <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>((d.dialog_num <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> d <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> existing), default<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb22-8">    session[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'current_dialog'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dnum</span>
<span id="cb22-9">    dialogs.insert(uid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>uid, dialog_num<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>dnum, name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>generate_slug(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>), messages<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'[]'</span>)</span>
<span id="cb22-10">    user_chats[(uid,dnum)] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_chat()</span>
<span id="cb22-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Div(hx_get<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'/dialog?dnum=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>dnum<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>, hx_trigger<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'load'</span>, hx_target<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#content'</span>, hx_swap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'innerHTML'</span>)</span></code></pre></div></div>
<p>:::</p>
</section>
<section id="session-persistance" class="level3">
<h3 class="anchored" data-anchor-id="session-persistance">Session Persistance</h3>
<p>::: {#67b4dc4e .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:01.506942+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb23" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb23-1">user_chats <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span></code></pre></div></div>
<p>:::</p>
<p>I’ll be handling session persistance with this <code>user_chats</code> dictionary. If my server restarts, it means <code>user_chats</code> will be erased and thus a new session will be created for all users. Users can input their restore code to retrieve back their data.</p>
<p>::: {#89ceda80 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:01.511262+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb24" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb24-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> ensure_user(session):</span>
<span id="cb24-2">    uid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> session.get(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'userid'</span>)</span>
<span id="cb24-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> uid <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> uid <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> users:</span>
<span id="cb24-4">        u <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> users.insert(restore_code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>generate_slug(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>))</span>
<span id="cb24-5">        session[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'userid'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> u.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span></span>
<span id="cb24-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> session[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'userid'</span>]</span></code></pre></div></div>
<p>:::</p>
<div id="cec05240" class="cell" data-time_run="2026-01-22T00:34:01.515256+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb25" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb25-1">fake_session <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span></code></pre></div></div>
</div>
<div id="597936b9" class="cell" data-time_run="2026-01-22T00:34:01.519295+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb26" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb26-1">uid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ensure_user(fake_session)</span>
<span id="cb26-2">fake_session, uid</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>({'userid': 1}, 1)</code></pre>
</div>
</div>
<p>::: {#9ac5a9ef .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:01.526400+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb28" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb28-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fastcore.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">all</span> <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span></span>
<span id="cb28-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> json</span>
<span id="cb28-3"></span>
<span id="cb28-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> ensure_dialog(session):</span>
<span id="cb28-5">    uid, dnum <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(session.get, (<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'userid'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'current_dialog'</span>))</span>
<span id="cb28-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (uid, dnum) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> user_chats: <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span></span>
<span id="cb28-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> dnum <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> (uid, dnum) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> dialogs: </span>
<span id="cb28-8">        d <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dialogs[(uid, dnum)]</span>
<span id="cb28-9">        user_chats[(uid, dnum)] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_chat(json.loads(d.messages))</span>
<span id="cb28-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>: create_dialog(session)</span></code></pre></div></div>
<p>:::</p>
<p><code>ensure_dialog</code> acts as a lazy loader for chat sessions. It first checks whether the user’s current dialog is already active in memory—if so, there’s nothing to do. If the dialog exists in the database but hasn’t been loaded yet, it retrieves the stored messages and reconstructs the chat object. Otherwise, when no dialog exists at all, it creates a fresh one for the user.</p>
<div id="34873f4b" class="cell" data-time_run="2026-01-22T00:34:01.530255+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb29" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb29-1">ensure_dialog(fake_session)</span>
<span id="cb29-2">user_chats</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>{(1, 1): (&lt;lisette.core.Chat at 0x70ee1a6efda0&gt;,
  &lt;IPython.terminal.interactiveshell.TerminalInteractiveShell at 0x70ee225f31a0&gt;)}</code></pre>
</div>
</div>
<p>::: {#f4bf5236 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:01.546425+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb31" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb31-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> contextvars <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> ContextVar</span>
<span id="cb31-2">current_lang <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ContextVar(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'lang'</span>, default<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'en'</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> current_lang</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>&lt;ContextVar name='lang' default='en' at 0x70ee19141df0&gt;</code></pre>
</div>
<p>:::</p>
<p>Every time a request is made, a new <code>ContextVar</code> is created. This is a way I can keep language preferences seperate for each user.</p>
<p>::: {#f4830cbf .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:01.551464+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb33" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb33-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb33-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> setsession(session):</span>
<span id="cb33-3">    current_lang.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(session.setdefault(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'lang'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'en'</span>))</span>
<span id="cb33-4">    uid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ensure_user(session)</span>
<span id="cb33-5">    ensure_dialog(session)</span></code></pre></div></div>
<p>:::</p>
<div id="217c47ba" class="cell" data-time_run="2026-01-22T00:34:01.559257+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb34" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb34-1">prev(setsession)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe src="../../setsession" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<p>The cookie only stores the user id. The data for the user is stored inside the current Python runtime. Once the runtime ends, the data is lost. The database permanently stores everything.</p>
<div id="b7100b29" class="cell" data-time_run="2026-01-22T00:34:01.563685+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb35" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb35-1">users()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>[User(id=1, restore_code='provocative-lori-of-acceptance')]</code></pre>
</div>
</div>
<div id="cee82adb" class="cell" data-time_run="2026-01-22T00:34:01.568674+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb37" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb37-1">dialogs()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>[Dialog(id=None, uid=1, dialog_num=1, name='viridian-pegasus', messages='[]', server_session=None)]</code></pre>
</div>
</div>
<div id="a89acb85" class="cell" data-time_run="2026-01-22T00:34:01.573660+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb39" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb39-1">user_chats</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>{(1, 1): (&lt;lisette.core.Chat at 0x70ee1a6efda0&gt;,
  &lt;IPython.terminal.interactiveshell.TerminalInteractiveShell at 0x70ee225f31a0&gt;)}</code></pre>
</div>
</div>
<div id="32122c5b" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb41" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb41-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb41-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> debug(session):</span>
<span id="cb41-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Pre(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>(session)))</span>
<span id="cb41-4">prev(debug)</span></code></pre></div></div>
</div>
<p><img src="https://forbo7.github.io/forblog/images/31_solveit_in_solveit/1.png" class="img-fluid"></p>
<div id="eacb8df3" class="cell" data-time_run="2026-01-22T00:34:01.583556+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb42" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb42-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb42-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> reset(session):</span>
<span id="cb42-3">    session.clear()</span>
<span id="cb42-4">    users.delete_where()</span>
<span id="cb42-5">    dialogs.delete_where()</span>
<span id="cb42-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> session</span></code></pre></div></div>
</div>
<p>I won’t be exporting these two routes into the final application, else it’d allow users to mess around with other users!</p>
</section>
<section id="localization" class="level3">
<h3 class="anchored" data-anchor-id="localization">Localization</h3>
<p>A translation dictionary stores the strings for both Chinese and English. The helper function <code>t()</code> performs the localization.</p>
<p>::: {#95173331 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ hide_input=‘true’ time_run=‘2026-01-22T00:34:01.589178+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb43" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb43-1">T <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb43-2">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'zh'</span>: {</span>
<span id="cb43-3">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'input_placeholder'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'输入内容···'</span>,</span>
<span id="cb43-4">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'submit'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'提交'</span>,</span>
<span id="cb43-5">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'ask_model'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'问问模型···'</span>,</span>
<span id="cb43-6">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'your_code'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'你的代码···'</span>,</span>
<span id="cb43-7">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'any_thoughts'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'有啥想法···'</span>,</span>
<span id="cb43-8">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'enter_code'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'输入代码···'</span>,</span>
<span id="cb43-9">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'code'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'代码'</span>,</span>
<span id="cb43-10">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'prompt'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'题词'</span>,</span>
<span id="cb43-11">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'note'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'笔记'</span>,</span>
<span id="cb43-12">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tab'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'标签'</span>,</span>
<span id="cb43-13">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'all_dialogs'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'所有对话'</span>,</span>
<span id="cb43-14">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'new_dialog'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'新对话'</span>,</span>
<span id="cb43-15">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'delete'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'删除'</span>,</span>
<span id="cb43-16">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'save'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'保存'</span>,</span>
<span id="cb43-17">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'solveit_lite'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'solveit-轻量版'</span>,</span>
<span id="cb43-18">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'footer'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'由 FastHTML 匠心打造'</span>,</span>
<span id="cb43-19">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'restore_code'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'恢复码'</span>,</span>
<span id="cb43-20">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'restore_failed'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'‼ 恢复失败'</span>,</span>
<span id="cb43-21">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'restore_error'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'找不到与此恢复码关联的账户，请检查后重试。'</span>,</span>
<span id="cb43-22">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'enter_restore_code'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'输入恢复码···'</span>,</span>
<span id="cb43-23">    },</span>
<span id="cb43-24">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'en'</span>: {</span>
<span id="cb43-25">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'input_placeholder'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Enter content...'</span>,</span>
<span id="cb43-26">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'submit'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Submit'</span>,</span>
<span id="cb43-27">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'ask_model'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Ask the model...'</span>,</span>
<span id="cb43-28">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'your_code'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Your code...'</span>,</span>
<span id="cb43-29">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'any_thoughts'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Any thoughts...'</span>,</span>
<span id="cb43-30">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'enter_code'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Enter code...'</span>,</span>
<span id="cb43-31">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'code'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Code'</span>,</span>
<span id="cb43-32">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'prompt'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Prompt'</span>,</span>
<span id="cb43-33">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'note'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Note'</span>,</span>
<span id="cb43-34">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tab'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Tab'</span>,</span>
<span id="cb43-35">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'all_dialogs'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'All Dialogs'</span>,</span>
<span id="cb43-36">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'new_dialog'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'New Dialog'</span>,</span>
<span id="cb43-37">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'delete'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Delete'</span>,</span>
<span id="cb43-38">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'save'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Save'</span>,</span>
<span id="cb43-39">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'solveit_lite'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'solveit-lite'</span>,</span>
<span id="cb43-40">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'footer'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Crafted with FastHTML'</span>,</span>
<span id="cb43-41">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'restore_code'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Restore Code'</span>,</span>
<span id="cb43-42">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'restore_failed'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'‼ Restore Failed'</span>,</span>
<span id="cb43-43">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'restore_error'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'No account found with this restore code. Please check and try again.'</span>,</span>
<span id="cb43-44">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'enter_restore_code'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Enter restore code...'</span>,</span>
<span id="cb43-45">    }</span>
<span id="cb43-46">}</span></code></pre></div></div>
<p>:::</p>
<p>::: {#f66dc855 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:01.593643+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb44" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb44-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> t(key, session<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>): </span>
<span id="cb44-2">    lang <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> session.get(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'lang'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'zh'</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> session <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> current_lang.get()</span>
<span id="cb44-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> T[lang].get(key, key)</span></code></pre></div></div>
<p>:::</p>
<div id="e3eddbdf" class="cell" data-time_run="2026-01-22T00:34:01.598015+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb45" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb45-1">t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'ask_model'</span>, {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'lang'</span>:<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'zh'</span>})</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>'问问模型···'</code></pre>
</div>
</div>
</section>
<section id="chat-bubbles" class="level3">
<h3 class="anchored" data-anchor-id="chat-bubbles">Chat Bubbles</h3>
<p>Bubbles that display the dialog content. Each bubble type has its own color scheme—blue for code, red for prompts, and green for notes.</p>
<p>::: {#4a5b2004 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:01.603161+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb47" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb47-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> Bubble(text, color, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'q'</span>, marked<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>):</span>
<span id="cb47-2">    colors <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb47-3">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'code'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'border-blue-500 bg-blue-50'</span>,</span>
<span id="cb47-4">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'note'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'border-green-500 bg-green-50'</span>,</span>
<span id="cb47-5">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'prompt'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'border-red-500 bg-red-50'</span></span>
<span id="cb47-6">    }</span>
<span id="cb47-7">    cls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'marked'</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> marked <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'ml-6'</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'r'</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> flex w-max max-w-[75%] flex-col gap-2 rounded-lg px-3 py-2 text-sm border-2 </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>colors[color]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span></span>
<span id="cb47-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Div(text, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>cls)</span></code></pre></div></div>
<p>:::</p>
<div id="8576ee05" class="cell" data-time_run="2026-01-22T00:34:01.608117+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb48" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb48-1">prev(Bubble(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'**嗨喽**'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'note'</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_34x6U4i3QgWOfs8gF0Af-A&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
     <div class=&quot;marked  flex w-max max-w-[75%] flex-col gap-2 rounded-lg px-3 py-2 text-sm border-2 border-green-500 bg-green-50&quot;>**嗨喽**</div>
   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<div id="52501953" class="cell" data-time_run="2026-01-22T00:34:01.620761+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb49" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb49-1">prev(Div(</span>
<span id="cb49-2">    Bubble(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'嗨！'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'prompt'</span>),</span>
<span id="cb49-3">    Bubble(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'哈喽！'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'prompt'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'r'</span>)</span>
<span id="cb49-4">))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_5q6rS-FnQcC_yo66hZunZw&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
     <div>
       <div class=&quot;marked  flex w-max max-w-[75%] flex-col gap-2 rounded-lg px-3 py-2 text-sm border-2 border-red-500 bg-red-50&quot;>嗨！</div>
       <div class=&quot;marked ml-6 flex w-max max-w-[75%] flex-col gap-2 rounded-lg px-3 py-2 text-sm border-2 border-red-500 bg-red-50&quot;>哈喽！</div>
     </div>
   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<div id="b3329ee1" class="cell" data-time_run="2026-01-22T00:34:01.629036+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb50" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb50-1">prev(Bubble(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'''</span></span>
<span id="cb50-2"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">```py</span></span>
<span id="cb50-3"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">print('嗨！！！')</span></span>
<span id="cb50-4"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'''</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'code'</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_YFilX3ZJTliSsC-UV4jZSw&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
     <div class=&quot;marked  flex w-max max-w-[75%] flex-col gap-2 rounded-lg px-3 py-2 text-sm border-2 border-blue-500 bg-blue-50&quot;>
```py
print('嗨！！！')
</div>
   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
</section>
<section id="component-wrappers" class="level3">
<h3 class="anchored" data-anchor-id="component-wrappers">Component Wrappers</h3>
<p>::: {#06830b37 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:01.636405+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb51" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb51-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> fasthtml.components <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> fc</span></code></pre></div></div>
<p>:::</p>
<p>::: {#0db9e155 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:01.640925+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb52" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb52-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> mk_comp(name, def_cls):</span>
<span id="cb52-2">    comp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">getattr</span>(fc, name)</span>
<span id="cb52-3">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">globals</span>()[name] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, var<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs: comp(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>def_cls<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}{</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"-"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>var <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> var <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>cls<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs)</span></code></pre></div></div>
<p>:::</p>
<p>This wrapper will allow us to define HTML components with Basecoat styling without redundantly stating what that component is.</p>
<p>Before:</p>
<div id="9fe29f38" class="cell" data-time_run="2026-01-22T00:34:01.645789+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb53" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb53-1">prev(Button(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'🔘'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'btn'</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_wPSsjh-xShy0E6KlF2xZhA&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
<button class=&quot;btn&quot;>🔘</button>   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<div id="b92813c9" class="cell" data-time_run="2026-01-22T00:34:01.653563+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb54" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb54-1">prev(Button(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'🔘'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'btn-destructive'</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_dn0Weor9QM_BG9rkmjWdPg&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
<button class=&quot;btn-destructive&quot;>🔘</button>   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<p>::: {#2e0f1420 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:01.661349+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb55" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb55-1">mk_comp(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Button'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'btn'</span>)</span>
<span id="cb55-2">mk_comp(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Input'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'input'</span>)</span>
<span id="cb55-3">mk_comp(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Textarea'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'textarea'</span>)</span>
<span id="cb55-4">mk_comp(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Label'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'label'</span>)</span></code></pre></div></div>
<p>:::</p>
<p>After:</p>
<div id="1f3f4ef0" class="cell" data-time_run="2026-01-22T00:34:01.666016+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb56" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb56-1">prev(Button(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'🔘'</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_I5E3BaKwTty2oLZFYCOtag&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
<button class=&quot;btn &quot;>🔘</button>   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<div id="6b7cadcd" class="cell" data-time_run="2026-01-22T00:34:01.675653+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb57" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb57-1">prev(Button(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'🔘'</span>, var<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'destructive'</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_DrZqLJJoR4erbgwSjnlh8Q&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
<button class=&quot;btn-destructive &quot;>🔘</button>   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<div id="0f0d9e38" class="cell" data-time_run="2026-01-22T00:34:01.682473+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb58" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb58-1">to_xml(Button(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'🔘'</span>)), to_xml(Button(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'🔘'</span>, var<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'destructive'</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>('&lt;button class="btn "&gt;🔘&lt;/button&gt;',
 '&lt;button class="btn-destructive "&gt;🔘&lt;/button&gt;')</code></pre>
</div>
</div>
</section>
<section id="input-box" class="level3">
<h3 class="anchored" data-anchor-id="input-box">Input Box</h3>
<p>The input area that will be used for entering messages to the dialog.</p>
<p>::: {#ae807178 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:01.687299+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb60" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb60-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> Inp(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'text'</span>, placeholder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'输入内容···'</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'inp'</span>, oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs): </span>
<span id="cb60-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Textarea(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'text'</span>, rows<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, placeholder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>placeholder, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'font-mono'</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>(hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'true'</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> oob <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> {}), <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs)</span></code></pre></div></div>
<p>:::</p>
<div id="5c85740e" class="cell" data-time_run="2026-01-22T00:34:01.692045+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb61" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb61-1">prev(Inp())</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_SSBiqWjjROeZWow61_hEEQ&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
<textarea type=&quot;text&quot; rows=&quot;1&quot; placeholder=&quot;输入内容···&quot; id=&quot;inp&quot; class=&quot;textarea font-mono&quot; name=&quot;inp&quot;></textarea>   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<div id="3b0017be" class="cell" data-time_run="2026-01-22T00:34:01.699737+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb62" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb62-1">to_xml(Inp())</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>'&lt;textarea type="text" rows="1" placeholder="输入内容···" id="inp" class="textarea font-mono" name="inp"&gt;&lt;/textarea&gt;'</code></pre>
</div>
</div>
</section>
<section id="button" class="level3">
<h3 class="anchored" data-anchor-id="button">Button</h3>
<div id="a3dd6f2f" class="cell" data-time_run="2026-01-22T00:34:01.705697+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb64" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb64-1">prev(Button(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'提交'</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'submit'</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_qXzP6u6kRtexYWRMRM1kdw&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
<button type=&quot;submit&quot; class=&quot;btn &quot;>提交</button>   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
</section>
<section id="route-helper-functions" class="level3">
<h3 class="anchored" data-anchor-id="route-helper-functions">Route Helper Functions</h3>
<p>Helper functions for managing chat sessions and rendering responses. <code>get_chat</code> retrieves the active chat and shell for the current user’s dialog. <code>sync_hist</code> persists the conversation history to the database. <code>mk_reply</code> generates the UI response—a pair of bubbles (user input and model output) along with an OOB swap to clear the input field.</p>
<div id="d3c8d251" class="cell" data-time_run="2026-01-22T00:34:01.712683+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb65" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb65-1">user_chats</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>{(1, 1): (&lt;lisette.core.Chat at 0x70ee1a6efda0&gt;,
  &lt;IPython.terminal.interactiveshell.TerminalInteractiveShell at 0x70ee225f31a0&gt;)}</code></pre>
</div>
</div>
<div id="ca673239" class="cell" data-time_run="2026-01-22T00:34:01.717199+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb67" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb67-1">fake_session <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'userid'</span>:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'current_dialog'</span>:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>}</span></code></pre></div></div>
</div>
<p>::: {#7eba2cc7 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:01.725230+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb68" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb68-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_chat(session): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> user_chats[(session[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'userid'</span>], session[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'current_dialog'</span>])]</span></code></pre></div></div>
<p>:::</p>
<div id="cdf98500" class="cell" data-time_run="2026-01-22T00:34:01.729644+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb69" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb69-1">get_chat(fake_session)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>(&lt;lisette.core.Chat at 0x70ee1a6efda0&gt;,
 &lt;IPython.terminal.interactiveshell.TerminalInteractiveShell at 0x70ee225f31a0&gt;)</code></pre>
</div>
</div>
<p>::: {#649b261d .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:01.734433+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb71" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb71-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> sync_hist(session, hist): dialogs.update(uid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>session[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'userid'</span>], dialog_num<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>session[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'current_dialog'</span>], messages<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>json.dumps([h.model_dump() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">hasattr</span>(h, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'model_dump'</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> h <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> h <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> hist]))</span></code></pre></div></div>
<p>:::</p>
<div id="d862c7c5" class="cell" data-time_run="2026-01-22T00:34:01.741455+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb72" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb72-1">c <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Chat(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'moonshot/kimi-k2-0711-preview'</span>, sp<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>sp)</span>
<span id="cb72-2">c(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'你是谁？'</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> c.hist</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>[{'role': 'user', 'content': '你是谁？'},
 Message(content='我是Kimi，由月之暗面科技有限公司训练的大语言模型。很高兴为你提供帮助！', role='assistant', tool_calls=None, function_call=None, provider_specific_fields={'refusal': None})]</code></pre>
</div>
</div>
<div id="3bdc4051" class="cell" data-time_run="2026-01-22T00:34:02.706286+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb74" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb74-1">sync_hist(fake_session, c.hist)</span></code></pre></div></div>
</div>
<div id="1fd1880e" class="cell" data-time_run="2026-01-22T00:34:02.711896+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb75" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb75-1">json.loads(dialogs[(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)].messages)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>[{'role': 'user', 'content': '你是谁？'},
 {'content': '我是Kimi，由月之暗面科技有限公司训练的大语言模型。很高兴为你提供帮助！',
  'role': 'assistant',
  'tool_calls': None,
  'function_call': None,
  'provider_specific_fields': {'refusal': None}}]</code></pre>
</div>
</div>
<p>::: {#c862e101 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:02.717276+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb77" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb77-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> mk_reply(inp, out, color, name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'inp'</span>, placeholder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'输入内容···'</span>): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Inp(oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>name, placeholder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>placeholder, onkeydown<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"if(event.shiftKey &amp;&amp; event.key==='Enter') { event.preventDefault(); this.form.requestSubmit(); }"</span>), Div(cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'space-y-0.5'</span>)(</span>
<span id="cb77-2">    Bubble(inp, color), </span>
<span id="cb77-3">    Bubble(out, color, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'r'</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> out <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>)</span></code></pre></div></div>
<p>:::</p>
<div id="f03287fe" class="cell" data-time_run="2026-01-22T00:34:02.722413+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb78" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb78-1">prev(mk_reply(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'呵呵'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'哈哈'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'prompt'</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_2pjxXAnyTr6szUdiW_Ismw&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
<textarea type=&quot;text&quot; rows=&quot;1&quot; placeholder=&quot;输入内容···&quot; hx-swap-oob=&quot;true&quot; name=&quot;inp&quot; onkeydown=&quot;if(event.shiftKey &amp;amp;&amp;amp; event.key==='Enter') { event.preventDefault(); this.form.requestSubmit(); }&quot; id=&quot;inp&quot; class=&quot;textarea font-mono&quot;></textarea>     <div class=&quot;space-y-0.5&quot;>
       <div class=&quot;marked  flex w-max max-w-[75%] flex-col gap-2 rounded-lg px-3 py-2 text-sm border-2 border-red-500 bg-red-50&quot;>呵呵</div>
       <div class=&quot;marked ml-6 flex w-max max-w-[75%] flex-col gap-2 rounded-lg px-3 py-2 text-sm border-2 border-red-500 bg-red-50&quot;>哈哈</div>
     </div>
   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
</section>
<section id="llm-route" class="level3">
<h3 class="anchored" data-anchor-id="llm-route">LLM Route</h3>
<div id="f512daec" class="cell" data-time_run="2026-01-22T00:34:02.733558+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb79" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb79-1">r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> c(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'嗨'</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> r.choices[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].message.content</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>'嗨！有什么我可以帮你的吗？'</code></pre>
</div>
</div>
<p>::: {#744b0ef0 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:03.555060+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb81" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb81-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> add_hist(hist, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>, content<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>, role<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'user'</span>):</span>
<span id="cb81-2">    hist.append(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>(role<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>role, content<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>content, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span>))</span></code></pre></div></div>
<p>:::</p>
<p>I’ve added a <code>type</code> key to allow me to know in what style to render the message (blue for <code>'code'</code>, red for <code>'prompt'</code>, and green for <code>'note'</code>) when I load them.</p>
<div id="6155227b" class="cell" data-time_run="2026-01-22T00:34:03.559630+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb82" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb82-1">add_hist(c.hist, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'note'</span>, content<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'这只是一张便条'</span>)</span>
<span id="cb82-2">c.hist</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>[{'role': 'user', 'content': '你是谁？'},
 Message(content='我是Kimi，由月之暗面科技有限公司训练的大语言模型。很高兴为你提供帮助！', role='assistant', tool_calls=None, function_call=None, provider_specific_fields={'refusal': None}),
 {'role': 'user', 'content': '嗨'},
 Message(content='嗨！有什么我可以帮你的吗？', role='assistant', tool_calls=None, function_call=None, provider_specific_fields={'refusal': None}),
 {'role': 'user', 'content': '这只是一张便条', 'type': 'note'}]</code></pre>
</div>
</div>
<p>::: {#e8fb36a9 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:03.565395+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb84" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb84-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> json</span>
<span id="cb84-2"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb84-3"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> ask_llm(qry:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, session):</span>
<span id="cb84-4">    c,sh <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_chat(session)</span>
<span id="cb84-5">    res <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> c(qry)</span>
<span id="cb84-6">    content <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> res.choices[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].message.content</span>
<span id="cb84-7">    c.hist[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'type'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'prompt'</span></span>
<span id="cb84-8">    c.hist[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'type'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'prompt'</span></span>
<span id="cb84-9">    sync_hist(session, c.hist)</span>
<span id="cb84-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> mk_reply(qry, content, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'prompt'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'qry'</span>, t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'ask_model'</span>))</span></code></pre></div></div>
<p>:::</p>
<div id="0903d3d5" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb85" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb85-1">prev(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'/ask_llm?qry=你好'</span>)</span></code></pre></div></div>
</div>
<p><img src="https://forbo7.github.io/forblog/images/31_solveit_in_solveit/2.png" class="img-fluid"></p>
<p><code>ask_llm</code>, alongside quering the model, stores the conversation with a <code>type</code> marker for rendering and syncs the history to the database.</p>
<p>::: {#a3bcde66 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:03.574612+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb86" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb86-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> test(inp):</span>
<span id="cb86-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Div(Div(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'msgs'</span>),</span>
<span id="cb86-3">    Form(hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ask_llm, hx_target<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#msgs'</span>, hx_swap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'beforeend'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'flex items-center space-x-2'</span>)(inp, Button(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'提交'</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'submit'</span>)))</span></code></pre></div></div>
<p>:::</p>
<div id="d4a24dcc" class="cell" data-time_run="2026-01-22T00:34:03.580061+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb87" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb87-1">prev(test(Inp(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'qry'</span>)))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_sOwJPhU5QG2fgQZgOB898g&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
     <div>
       <div id=&quot;msgs&quot;></div>
<form hx-post=&quot;/ask_llm&quot; hx-target=&quot;#msgs&quot; hx-swap=&quot;beforeend&quot; class=&quot;flex items-center space-x-2&quot;><textarea type=&quot;text&quot; rows=&quot;1&quot; placeholder=&quot;输入内容···&quot; id=&quot;qry&quot; class=&quot;textarea font-mono&quot; name=&quot;qry&quot;></textarea><button type=&quot;submit&quot; class=&quot;btn &quot;>提交</button></form>     </div>
   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<div id="883fbfc1" class="cell" data-time_run="2026-01-22T00:34:20.304244+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb88" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb88-1">user_chats</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>{(1, 1): (&lt;lisette.core.Chat at 0x70ee1a6efda0&gt;,
  &lt;IPython.terminal.interactiveshell.TerminalInteractiveShell at 0x70ee225f31a0&gt;)}</code></pre>
</div>
</div>
</section>
<section id="code-route" class="level3">
<h3 class="anchored" data-anchor-id="code-route">Code Route</h3>
<div id="76deb6dd" class="cell" data-time_run="2026-01-22T00:34:21.390093+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb90" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb90-1">sh <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_shell()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> sh</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>&lt;IPython.terminal.interactiveshell.TerminalInteractiveShell at 0x70ee190c31d0&gt;</code></pre>
</div>
</div>
<div id="a087eec5" class="cell" data-time_run="2026-01-22T00:34:21.967822+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb92" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb92-1">??get_shell</span></code></pre></div></div>
<div class="cell-output cell-output-display cell-output-markdown">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb93" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb93-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_shell()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span>TerminalInteractiveShell:</span>
<span id="cb93-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"Get a `TerminalInteractiveShell` with minimal functionality"</span></span>
<span id="cb93-3">    sh <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> TerminalInteractiveShell()</span>
<span id="cb93-4">    sh.logger.log_output <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sh.history_manager.enabled <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span></span>
<span id="cb93-5">    dh <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sh.displayhook</span>
<span id="cb93-6">    dh.finish_displayhook <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dh.write_output_prompt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dh.start_displayhook <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span>: <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="cb93-7">    dh.write_format_data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> format_dict, md_dict<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>: <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="cb93-8">    sh.logstart <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sh.automagic <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sh.autoindent <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span></span>
<span id="cb93-9">    sh.autocall <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb93-10">    sh.system <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> cmd: <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span></span>
<span id="cb93-11">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> sh</span></code></pre></div></div>
<p><strong>File:</strong> <code>/usr/local/lib/python3.12/site-packages/toolslm/shell.py</code></p>
</div>
</div>
<p><code>get_shell</code> relies on IPython under the hood.</p>
<p>::: {#0f20abdc .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:23.268921+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb94" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb94-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> ex(code, sh):</span>
<span id="cb94-2">    res <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> sh.run_cell(code)</span>
<span id="cb94-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> res.result <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> res.result <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> res.stdout</span></code></pre></div></div>
<p>:::</p>
<p>::: {#3cd307bc .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:23.654002+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb95" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb95-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb95-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> ex_code(code:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, session):</span>
<span id="cb95-3">    c,sh <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_chat(session)</span>
<span id="cb95-4">    add_hist(c.hist, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'code'</span>, <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'[INTERPRETER INPUT]</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">```py</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>code<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">```'</span>)</span>
<span id="cb95-5">    res <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ex(code, sh)</span>
<span id="cb95-6">    add_hist(c.hist, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'code'</span>, <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'[INTERPRETER OUTPUT]</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">```py</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>res<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">```'</span>, role<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'assistant'</span>)</span>
<span id="cb95-7">    sync_hist(session, c.hist)</span>
<span id="cb95-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> mk_reply(inp<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'```py</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>code<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">```'</span>, out<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'```py</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>res<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">```'</span>, color<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'code'</span>, name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'code'</span>, placeholder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'your_code'</span>))</span></code></pre></div></div>
<p>:::</p>
<p><code>ex_code</code> similarly also stores the conversation with a <code>type</code> marker and syncs with the database. A special <code>'[INTERPRETER INPUT/OUTPUT]'</code> marker is also added as indicators for the LLM.</p>
<div id="db08322b" class="cell" data-time_run="2026-01-22T00:34:24.700819+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb96" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb96-1">prev(Div(</span>
<span id="cb96-2">    Div(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'msgs'</span>),</span>
<span id="cb96-3">    Form(hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ex_code, hx_target<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#msgs'</span>, hx_swap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'beforeend'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'flex items-center space-x-2'</span>)(Inp(name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'code'</span>), Button(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'提交'</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'submit'</span>))</span>
<span id="cb96-4">))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_gpzn5PagQLu_sL3pcQnBjA&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
     <div>
       <div id=&quot;msgs&quot;></div>
<form hx-post=&quot;/ex_code&quot; hx-target=&quot;#msgs&quot; hx-swap=&quot;beforeend&quot; class=&quot;flex items-center space-x-2&quot;><textarea type=&quot;text&quot; rows=&quot;1&quot; placeholder=&quot;输入内容···&quot; name=&quot;code&quot; id=&quot;inp&quot; class=&quot;textarea font-mono&quot;></textarea><button type=&quot;submit&quot; class=&quot;btn &quot;>提交</button></form>     </div>
   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
</section>
<section id="note-route" class="level3">
<h3 class="anchored" data-anchor-id="note-route">Note Route</h3>
<p>::: {#a591691c .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:34.562110+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb97" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb97-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb97-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> add_note(note:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, session):</span>
<span id="cb97-3">    c,sh <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_chat(session)</span>
<span id="cb97-4">    add_hist(c.hist, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'note'</span>, content<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>note,)</span>
<span id="cb97-5">    sync_hist(session, c.hist)</span>
<span id="cb97-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> mk_reply(note, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'note'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'note'</span>, t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'any_thoughts'</span>))</span></code></pre></div></div>
<p>:::</p>
<div id="97613b2b" class="cell" data-time_run="2026-01-22T00:34:35.127191+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb98" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb98-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> test(inp):</span>
<span id="cb98-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Div(Div(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'msgs'</span>),</span>
<span id="cb98-3">    Form(hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>add_note, hx_target<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#msgs'</span>, hx_swap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'beforeend'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'flex items-center space-x-2'</span>)(inp, Button(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'提交'</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'submit'</span>)))</span></code></pre></div></div>
</div>
<div id="87d1a55b" class="cell" data-time_run="2026-01-22T00:34:36.919785+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb99" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb99-1">prev(test(Inp(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'note'</span>)))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_VCXLYIKUQ729Sx7Bs_EvCw&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
     <div>
       <div id=&quot;msgs&quot;></div>
<form hx-post=&quot;/add_note&quot; hx-target=&quot;#msgs&quot; hx-swap=&quot;beforeend&quot; class=&quot;flex items-center space-x-2&quot;><textarea type=&quot;text&quot; rows=&quot;1&quot; placeholder=&quot;输入内容···&quot; id=&quot;note&quot; class=&quot;textarea font-mono&quot; name=&quot;note&quot;></textarea><button type=&quot;submit&quot; class=&quot;btn &quot;>提交</button></form>     </div>
   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
</section>
<section id="editor-component" class="level3">
<h3 class="anchored" data-anchor-id="editor-component">Editor Component</h3>
<p>Three editor components for the different message types. Each editor is a form that posts to its corresponding route (ex_code, ask_llm, or add_note) and appends the result to the message area.</p>
<p>::: {#3da6f419 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:34:55.717291+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb100" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb100-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb100-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> code_editor(session): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Form(hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ex_code, hx_target<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#msgs'</span>, hx_swap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'beforeend'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'flex items-stretch space-x-2'</span>)(Inp(placeholder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'enter_code'</span>, session), name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'code'</span>, onkeydown<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"if(event.shiftKey &amp;&amp; event.key==='Enter') { event.preventDefault(); this.form.requestSubmit(); }"</span>), Button(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'submit'</span>, session), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'submit'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'self-stretch h-auto'</span>))</span></code></pre></div></div>
<p>:::</p>
<p>The editor routes need the session cookie for translations because each editor is loaded in a separate request. Since <code>ContextVar</code> resets with each new request, we need to re-set the language from the session at the start of each request.</p>
<div id="ab710ded" class="cell" data-time_run="2026-01-22T00:34:57.364902+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb101" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb101-1">prev(Div(Div(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'msgs'</span>),Div(hx_get<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>code_editor, hx_trigger<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'load'</span>)))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_TP4ozbZ9R6im9-QhRIq3kw&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
     <div>
       <div id=&quot;msgs&quot;></div>
       <div hx-get=&quot;/code_editor&quot; hx-trigger=&quot;load&quot;></div>
     </div>
   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<p>::: {#e85cd35e .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:35:18.553389+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb102" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb102-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb102-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> llm_editor(session): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Form(hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>ask_llm, hx_target<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#msgs'</span>, hx_swap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'beforeend'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'flex items-center space-x-2'</span>)(Inp(placeholder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'ask_model'</span>, session), name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'qry'</span>, onkeydown<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"if(event.shiftKey &amp;&amp; event.key==='Enter') { event.preventDefault(); this.form.requestSubmit(); }"</span>), Button(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'submit'</span>, session), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'submit'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'self-stretch h-auto'</span>))</span></code></pre></div></div>
<p>:::</p>
<div id="84f3f0c8" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb103" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb103-1">prev(llm_editor)</span></code></pre></div></div>
</div>
<p><img src="https://forbo7.github.io/forblog/images/31_solveit_in_solveit/3.png" class="img-fluid"></p>
<p>::: {#3f0d14d8 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:35:37.352665+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb104" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb104-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb104-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> note_editor(session): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Form(hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>add_note, hx_target<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#msgs'</span>, hx_swap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'beforeend'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'flex items-center space-x-2'</span>)(Inp(placeholder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'any_thoughts'</span>, session), name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'note'</span>, onkeydown<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"if(event.shiftKey &amp;&amp; event.key==='Enter') { event.preventDefault(); this.form.requestSubmit(); }"</span>), Button(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'submit'</span>, session), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'submit'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'self-stretch h-auto'</span>))</span></code></pre></div></div>
<p>:::</p>
<div id="3ce84ce7" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb105" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb105-1">prev(note_editor)</span></code></pre></div></div>
</div>
<div id="ae95e9e3" class="cell" data-time_run="2026-01-22T00:47:19.523133+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb106" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb106-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>[](..<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>images<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">31</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">_solveit_in_solveit</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">4.</span><span class="er" style="color: #AD0000;
background-color: null;
font-style: inherit;">png</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>/bin/bash: -c: line 1: syntax error near unexpected token `../images/31_solveit_in_solveit/4.png'
/bin/bash: -c: line 1: `[](../images/31_solveit_in_solveit/4.png)'</code></pre>
</div>
</div>
</section>
<section id="tabs" class="level3">
<h3 class="anchored" data-anchor-id="tabs">Tabs</h3>
<p>A tabbed navigation bar that lets users switch between the three editor types—code, prompt, and note. Each tab triggers an HTMX request to load the corresponding editor form into the editor container.</p>
<p>::: {#e2b96dec .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:39:32.407645+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb108" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb108-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> Tab(title, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span>, hx_post, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> fc.Button(title, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">-tab'</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'button'</span>, role<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tab'</span>, hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>hx_post, hx_target<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#editor'</span>, hx_swap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'innerHTML'</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs)</span></code></pre></div></div>
<p>:::</p>
<div id="3d564e72" class="cell" data-time_run="2026-01-22T00:39:35.982976+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb109" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb109-1">prev(Nav(Tab(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'标签'</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'test'</span>, hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>), cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'w-full'</span>, role<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tablist'</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_mALelgv5S2OwXq8-G3Ewxw&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
     <nav class=&quot;w-full&quot; role=&quot;tablist&quot;>
<button type=&quot;button&quot; role=&quot;tab&quot; hx-swap=&quot;innerHTML&quot; hx-target=&quot;#editor&quot; id=&quot;test-tab&quot; name=&quot;test-tab&quot;>标签</button>     </nav>
   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<p>::: {#355bf665 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:39:37.560871+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb110" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb110-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> TabBar(cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs): </span>
<span id="cb110-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Nav(</span>
<span id="cb110-3">        Tab(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'code'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'code'</span>, hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>code_editor),</span>
<span id="cb110-4">        Tab(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'prompt'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'qry'</span>, hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>llm_editor),</span>
<span id="cb110-5">        Tab(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'note'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'note'</span>, hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>note_editor),</span>
<span id="cb110-6">        cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'w-full </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>cls<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>, role<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tablist'</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs</span>
<span id="cb110-7">    )</span></code></pre></div></div>
<p>:::</p>
<div id="eb8c9010" class="cell" data-time_run="2026-01-22T00:39:39.897658+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb111" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb111-1">prev(Div(TabBar(), Div(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'editor'</span>), cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tabs w-full'</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_1osIrIiPS2_bxJ-sxvruzQ&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
     <div class=&quot;tabs w-full&quot;>
       <nav class=&quot;w-full &quot; role=&quot;tablist&quot;>
<button type=&quot;button&quot; role=&quot;tab&quot; hx-post=&quot;/code_editor&quot; hx-swap=&quot;innerHTML&quot; hx-target=&quot;#editor&quot; id=&quot;code-tab&quot; name=&quot;code-tab&quot;>Code</button><button type=&quot;button&quot; role=&quot;tab&quot; hx-post=&quot;/llm_editor&quot; hx-swap=&quot;innerHTML&quot; hx-target=&quot;#editor&quot; id=&quot;qry-tab&quot; name=&quot;qry-tab&quot;>Prompt</button><button type=&quot;button&quot; role=&quot;tab&quot; hx-post=&quot;/note_editor&quot; hx-swap=&quot;innerHTML&quot; hx-target=&quot;#editor&quot; id=&quot;note-tab&quot; name=&quot;note-tab&quot;>Note</button>       </nav>
       <div id=&quot;editor&quot;></div>
     </div>
   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
</section>
<section id="render-existing-messages" class="level3">
<h3 class="anchored" data-anchor-id="render-existing-messages">Render Existing Messages</h3>
<p>::: {#764bf26a .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:39:42.067948+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb112" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb112-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb112-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> load_messages(session):</span>
<span id="cb112-3">    c,sh <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_chat(session)</span>
<span id="cb112-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> c.hist:</span>
<span id="cb112-5">        role <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> i.get(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'role'</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">isinstance</span>(i, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> i.role</span>
<span id="cb112-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> role<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'user'</span>:      <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> Div(Bubble(i[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'content'</span>].replace(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'[INTERPRETER INPUT]</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>), i[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'type'</span>]), cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'space-y-0.5'</span>)</span>
<span id="cb112-7">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> role<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'assistant'</span>: <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> Div(Bubble(i[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'content'</span>].replace(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'[INTERPRETER OUTPUT]</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>), i[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'type'</span>], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'r'</span>), cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'space-y-0.5'</span>)</span></code></pre></div></div>
<p>:::</p>
<div id="a3420fbb" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb113" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb113-1">prev(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'/load_messages'</span>)</span></code></pre></div></div>
</div>
<p><img src="https://forbo7.github.io/forblog/images/31_solveit_in_solveit/5.png" class="img-fluid"></p>
</section>
<section id="dialog" class="level3">
<h3 class="anchored" data-anchor-id="dialog">Dialog</h3>
<p>The dialog component ties everything together—a title bar that supports inline editing, a message display area that loads existing conversation history, and the tabbed editor for adding new messages. Clicking a dialog name makes it editable, and saving updates the database immediately.</p>
<p>::: {#64ce33d2 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:40:04.037914+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb114" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb114-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb114-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> edit_dname(session):</span>
<span id="cb114-3">    dname <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dialogs[(session[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'userid'</span>], session[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'current_dialog'</span>])].name</span>
<span id="cb114-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Form(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'dname'</span>, hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>save_dname, hx_target<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#dname'</span>, hx_swap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'outerHTML'</span>)(</span>
<span id="cb114-5">        Input(value<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>dname, name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'newname'</span>, autofocus<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, onfocus<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'this.select()'</span>, required<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'text-2xl font-bold outline-none'</span>),</span>
<span id="cb114-6">        Button(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'save'</span>, session), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'submit'</span>)</span>
<span id="cb114-7">    )</span></code></pre></div></div>
<p>:::</p>
<p>::: {#9d6ae097 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:40:04.608020+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb115" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb115-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span> </span>
<span id="cb115-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> save_dname(session, newname:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>):</span>
<span id="cb115-3">    dialogs.update(uid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>session[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'userid'</span>], dialog_num<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>session[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'current_dialog'</span>], name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>newname)</span>
<span id="cb115-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> DialogTitle(newname)</span></code></pre></div></div>
<p>:::</p>
<p>::: {#dfb739b4 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:40:05.386759+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb116" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb116-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> DialogTitle(name): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> H1(name, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'text-2xl font-bold'</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'dname'</span>, hx_get<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>edit_dname, hx_target<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#dname'</span>, hx_swap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'outerHTML'</span>)</span></code></pre></div></div>
<p>:::</p>
<div id="fb800175" class="cell" data-time_run="2026-01-22T00:40:09.509853+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb117" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb117-1">prev(DialogTitle(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'对话'</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_k7gfueTcTcqBaOF87mC30w&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
     <h1 class=&quot;text-2xl font-bold&quot; id=&quot;dname&quot; hx-get=&quot;/edit_dname&quot; hx-target=&quot;#dname&quot; hx-swap=&quot;outerHTML&quot;>对话</h1>
   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<p>::: {#5f7ef951 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:40:10.636548+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb118" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb118-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb118-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> dialog(dnum:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>, session): </span>
<span id="cb118-3">    session[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'current_dialog'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dnum</span>
<span id="cb118-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Div(</span>
<span id="cb118-5">        DialogTitle(dialogs[(session[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'userid'</span>], dnum)].name),</span>
<span id="cb118-6">        Div(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'msgs'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'p-8 max-h-96 overflow-y-auto'</span>, hx_get<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>load_messages, hx_trigger<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'load'</span>),</span>
<span id="cb118-7">        TabBar(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tabbar'</span>),</span>
<span id="cb118-8">        Div(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'editor'</span>),</span>
<span id="cb118-9">        cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'tabs w-full'</span></span>
<span id="cb118-10">    )</span></code></pre></div></div>
<p>:::</p>
<div id="aec9fe41" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb119" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb119-1">prev(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'dialog?dnum=1'</span>)</span></code></pre></div></div>
</div>
<p><img src="https://forbo7.github.io/forblog/images/31_solveit_in_solveit/6.png" class="img-fluid"></p>
</section>
<section id="delete-dialog" class="level3">
<h3 class="anchored" data-anchor-id="delete-dialog">Delete Dialog</h3>
<p>::: {#493dcf03 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:40:29.905945+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb120" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb120-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb120-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> delete_dialog(session, dnum:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">int</span>):</span>
<span id="cb120-3">    uid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> session.get(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'userid'</span>)</span>
<span id="cb120-4">    dialogs.delete((uid, dnum))</span>
<span id="cb120-5">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">del</span> user_chats[(uid, dnum)]</span></code></pre></div></div>
<p>:::</p>
<div id="c90ef6df" class="cell" data-time_run="2026-01-22T00:40:30.470264+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb121" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb121-1">fake_session</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>{'userid': 1, 'current_dialog': 1}</code></pre>
</div>
</div>
<div id="ed94dd41" class="cell" data-time_run="2026-01-22T00:40:31.202402+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb123" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb123-1">users(), dialogs()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>([User(id=1, restore_code='provocative-lori-of-acceptance')],
 [Dialog(id=None, uid=1, dialog_num=1, name='viridian-pegasus', messages='[{"role": "user", "content": "\\u4f60\\u597d", "type": "prompt"}, {"content": "\\u4f60\\u597d\\uff01\\u6709\\u4ec0\\u4e48\\u6211\\u53ef\\u4ee5\\u5e2e\\u60a8\\u7684\\u5417\\uff1f", "role": "assistant", "tool_calls": null, "function_call": null, "provider_specific_fields": {"refusal": null}, "type": "prompt"}, {"role": "user", "content": "\\u54c8\\u55bd", "type": "prompt"}, {"content": "\\u54c8\\u55bd\\uff01\\u5f88\\u9ad8\\u5174\\u53c8\\u89c1\\u5230\\u4f60\\uff5e  \\n\\u4eca\\u5929\\u60f3\\u804a\\u70b9\\u4ec0\\u4e48\\uff0c\\u6216\\u8005\\u6709\\u4ec0\\u4e48\\u9700\\u8981\\u6211\\u5e2e\\u5fd9\\u7684\\uff1f", "role": "assistant", "tool_calls": null, "function_call": null, "provider_specific_fields": {"refusal": null}, "type": "prompt"}, {"role": "user", "content": "[INTERPRETER INPUT]\\n```py\\n1+1\\n```", "type": "code"}, {"role": "assistant", "content": "[INTERPRETER OUTPUT]\\n```py\\n2\\n```", "type": "code"}, {"role": "user", "content": "\\u4e00\\u5f20\\u4fbf\\u8d34", "type": "note"}, {"role": "user", "content": "[INTERPRETER INPUT]\\n```py\\n5**2\\n```", "type": "code"}, {"role": "assistant", "content": "[INTERPRETER OUTPUT]\\n```py\\n25\\n```", "type": "code"}, {"role": "user", "content": "\\u4f60\\u597d", "type": "prompt"}, {"content": "\\u4f60\\u597d\\uff01\\u770b\\u8d77\\u6765\\u4f60\\u521a\\u521a\\u8bd5\\u4e86 1+1 \\u548c 5**2\\uff0c\\u7ed3\\u679c\\u5206\\u522b\\u662f 2 \\u548c 25\\u3002  \\n\\u201c\\u4e00\\u5f20\\u4fbf\\u8d34\\u201d\\u662f\\u60f3\\u8ba9\\u6211\\u5e2e\\u4f60\\u5199\\u70b9\\u4ec0\\u4e48\\u5417\\uff1f\\u8fd8\\u662f\\u6709\\u4ec0\\u4e48\\u522b\\u7684\\u9700\\u6c42\\uff1f", "role": "assistant", "tool_calls": null, "function_call": null, "provider_specific_fields": {"refusal": null}, "type": "prompt"}]', server_session=None)])</code></pre>
</div>
</div>
<div id="8710493b" class="cell" data-time_run="2026-01-22T00:40:33.869075+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb125" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb125-1">user_chats</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>{(1, 1): (&lt;lisette.core.Chat at 0x70ee1a6efda0&gt;,
  &lt;IPython.terminal.interactiveshell.TerminalInteractiveShell at 0x70ee225f31a0&gt;)}</code></pre>
</div>
</div>
<div id="3b374041" class="cell" data-time_run="2026-01-22T00:40:34.881908+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb127" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb127-1">delete_dialog(fake_session, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span></code></pre></div></div>
</div>
<div id="e177237c" class="cell" data-time_run="2026-01-22T00:40:35.942293+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb128" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb128-1">users(), dialogs()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>([User(id=1, restore_code='provocative-lori-of-acceptance')], [])</code></pre>
</div>
</div>
<div id="987e82ba" class="cell" data-time_run="2026-01-22T00:40:37.249208+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb130" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb130-1">user_chats</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>{}</code></pre>
</div>
</div>
</section>
<section id="restore-dialog" class="level3">
<h3 class="anchored" data-anchor-id="restore-dialog">Restore Dialog</h3>
<p>The restore session feature allows users to recover their data if the server restarts or they switch devices. Users enter their unique restore code (generated at account creation), which looks up their account in the database. If found, it restores their session by setting the user ID, loading their first dialog, and redirecting to the main page. A destructive alert displays if the restore code is invalid.</p>
<p>::: {#b7ebe597 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:40:39.407474+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb132" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb132-1">insolveit <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'IN_SOLVEIT'</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> os.environ</span></code></pre></div></div>
<p>:::</p>
<div id="10d3508c" class="cell" data-time_run="2026-01-22T00:40:40.224216+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb133" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb133-1">insolveit</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>True</code></pre>
</div>
</div>
<p>I’ve created the <code>insolveit</code> check to determine whether the app is running in my SolveIt instance or whether as a deployed app.</p>
<p>::: {#7c59ce58 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:40:41.808713+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb135" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb135-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb135-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> restore_session(restore_code:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>, session):</span>
<span id="cb135-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (u<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:=</span>first(users(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'restore_code=?'</span>, [restore_code]))):</span>
<span id="cb135-4">        session[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'userid'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> u.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span></span>
<span id="cb135-5">        existing <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> dialogs(where<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'uid=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>u<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>)</span>
<span id="cb135-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> existing: session[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'current_dialog'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> existing[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].dialog_num</span>
<span id="cb135-7">        setsession(session)</span>
<span id="cb135-8">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> HtmxResponseHeaders(redirect<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'/main'</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> insolveit <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'/'</span>)</span>
<span id="cb135-9">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span>: <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Div(cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'alert-destructive'</span>)(H2(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'restore_failed'</span>)), Section(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'restore_error'</span>)))</span>
<span id="cb135-10"></span>
<span id="cb135-11">    session[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'userid'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> first(users(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'restore_code=?'</span>, [restore_code])).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span></span>
<span id="cb135-12">    setsession(session)</span></code></pre></div></div>
<p>:::</p>
<div id="55d6f5c1" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb136" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb136-1">prev(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'/restore_session?restore_code=haha'</span>)</span></code></pre></div></div>
</div>
<p><img src="https://forbo7.github.io/forblog/images/31_solveit_in_solveit/7.png" class="img-fluid"></p>
<div id="339caae0" class="cell" data-time_run="2026-01-22T00:41:13.506574+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb137" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb137-1">user_chats</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>{}</code></pre>
</div>
</div>
<div id="df810c65" class="cell" data-time_run="2026-01-22T00:41:14.234217+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb139" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb139-1">users[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].restore_code</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>'provocative-lori-of-acceptance'</code></pre>
</div>
</div>
<div id="e39a0de7" class="cell" data-time_run="2026-01-22T00:41:19.073664+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb141" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb141-1">user_chats <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span>
<span id="cb141-2">prev(restore_session.to(restore_code<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>users[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>].restore_code))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe src="../../restore_session?restore_code=provocative-lori-of-acceptance" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<div id="e4480c35" class="cell" data-time_run="2026-01-22T00:41:54.260492+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb142" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb142-1">user_chats</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>{(1, 1): (&lt;lisette.core.Chat at 0x70ee0bf336e0&gt;,
  &lt;IPython.terminal.interactiveshell.TerminalInteractiveShell at 0x70ee19188fb0&gt;)}</code></pre>
</div>
</div>
<div id="712e7431" class="cell" data-time_run="2026-01-22T00:42:03.520503+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb144" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb144-1">prev(Div(</span>
<span id="cb144-2">    Form(hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>restore_session, hx_target<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#alert-area'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'flex items-end gap-2'</span>)(</span>
<span id="cb144-3">        Div()(</span>
<span id="cb144-4">            Label(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'恢复码'</span>, fr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'restore_code'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mb-2'</span>),</span>
<span id="cb144-5">            Input(placeholder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'looks-like-this'</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'text'</span>, name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'restore_code'</span>)</span>
<span id="cb144-6">        ),</span>
<span id="cb144-7">        Button(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'提交'</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'submit'</span>)</span>
<span id="cb144-8">    ),</span>
<span id="cb144-9">    Div(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'alert-area'</span>)</span>
<span id="cb144-10">))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_q7QSnSCySD_yuaCN8jW8Rg&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
     <div>
<form hx-post=&quot;/restore_session&quot; hx-target=&quot;#alert-area&quot; class=&quot;flex items-end gap-2&quot;>         <div>
<label for=&quot;restore_code&quot; class=&quot;label mb-2&quot;>恢复码</label>           <input placeholder=&quot;looks-like-this&quot; type=&quot;text&quot; name=&quot;restore_code&quot; class=&quot;input &quot;>
         </div>
<button type=&quot;submit&quot; class=&quot;btn &quot;>提交</button></form>       <div id=&quot;alert-area&quot;></div>
     </div>
   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<p>::: {#b997e64f .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:42:07.092837+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb145" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb145-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> RestoreForm(session, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'restore-form'</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs):</span>
<span id="cb145-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Form(hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>restore_session, hx_target<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#alert-box'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'flex items-end gap-2'</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs)(</span>
<span id="cb145-3">        Div(</span>
<span id="cb145-4">            Label(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'restore_code'</span>), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">' · '</span>, users[session[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'userid'</span>]].restore_code, fr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'restore_code'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mb-2'</span>),</span>
<span id="cb145-5">            Input(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'text'</span>, name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'restore_code'</span>, placeholder<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'enter_restore_code'</span>))</span>
<span id="cb145-6">        ),</span>
<span id="cb145-7">        Button(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'submit'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'submit'</span>)</span>
<span id="cb145-8">    )</span></code></pre></div></div>
<p>:::</p>
<div id="d3f6971a" class="cell" data-time_run="2026-01-22T00:42:10.211228+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb146" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb146-1">prev(RestoreForm(fake_session))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_z-mQL0X7R1qfFXWTNVyukA&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
<form hx-post=&quot;/restore_session&quot; hx-target=&quot;#alert-box&quot; class=&quot;flex items-end gap-2&quot; id=&quot;restore-form&quot;>       <div>
<label for=&quot;restore_code&quot; class=&quot;label mb-2&quot;>Restore Code · provocative-lori-of-acceptance</label>         <input type=&quot;text&quot; name=&quot;restore_code&quot; placeholder=&quot;Enter restore code...&quot; class=&quot;input &quot;>
       </div>
<button type=&quot;submit&quot; class=&quot;btn &quot;>Submit</button></form>   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
</section>
<section id="dialog-list" class="level3">
<h3 class="anchored" data-anchor-id="dialog-list">Dialog List</h3>
<p>The dialog list component displays all dialogs belonging to the current user. The <code>display_dialogs</code> route fetches all user dialogs from the database and includes a “new dialog” card that triggers dialog creation. The restore code form is also embedded here, allowing users to recover their session from a different device.</p>
<p>::: {#7fde0067 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:42:13.946257+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb147" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb147-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb147-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> current_dialog(session): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> dialog(session.get(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'current_dialog'</span>), session)</span></code></pre></div></div>
<p>:::</p>
<p>::: {#d1206a9d .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:42:14.672987+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb148" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb148-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> DialogCard(d): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Div(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'dialog-</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>uid<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}{</span>d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>dialog_num<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'card p-4 hover:bg-gray-100 flex flex-row justify-between items-center'</span>)(</span>
<span id="cb148-2">    Span(hx_get<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>dialog.to(dnum<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>d.dialog_num), hx_target<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#content'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'cursor-pointer'</span>)(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'💬 '</span>, d.name), </span>
<span id="cb148-3">    Button(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'delete'</span>), var<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'destructive'</span>, hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>delete_dialog.to(dnum<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>d.dialog_num), hx_swap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'delete'</span>, hx_target<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'#dialog-</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>uid<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}{</span>d<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>dialog_num<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>)</span>
<span id="cb148-4">)</span></code></pre></div></div>
<p>:::</p>
<div id="abb01407" class="cell" data-time_run="2026-01-22T00:42:17.474620+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb149" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb149-1">prev(DialogCard(first(dialogs())))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_6Y1bRgKQTmC8z9EN5_DnGA&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
     <div id=&quot;dialog-11&quot; class=&quot;card p-4 hover:bg-gray-100 flex flex-row justify-between items-center&quot;>
<span hx-get=&quot;/dialog?dnum=1&quot; hx-target=&quot;#content&quot; class=&quot;cursor-pointer&quot;>💬 gleaming-tortoise</span><button hx-post=&quot;/delete_dialog?dnum=1&quot; hx-swap=&quot;delete&quot; hx-target=&quot;#dialog-11&quot; class=&quot;btn-destructive &quot;>Delete</button>     </div>
   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
<p>::: {#4151e92e .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:42:23.354678+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb150" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb150-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb150-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> display_dialogs(session):</span>
<span id="cb150-3">    ds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> L(dialogs(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'uid=?'</span>, [session.get(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'userid'</span>)]))</span>
<span id="cb150-4">    ds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ds.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> d: DialogCard(d))</span>
<span id="cb150-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Div(cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'flex flex-col gap-2 max-w-xl'</span>)(</span>
<span id="cb150-6">        Div(cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'flex items-center justify-between gap-4'</span>)(H1(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'all_dialogs'</span>, session), cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'text-2xl font-bold'</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'all-dialogs-title'</span>), RestoreForm(session)), </span>
<span id="cb150-7">        Div(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'alert-box'</span>),</span>
<span id="cb150-8">        Div(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'➕'</span>, Span(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'new_dialog'</span>, session), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'new-dialog-text'</span>), cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'card p-4 hover:bg-gray-100 cursor-pointer border-2 border-dashed flex flex-row items-center gap-2'</span>, hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>create_dialog, hx_target<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#content'</span>),</span>
<span id="cb150-9">        Div(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>ds, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'flex flex-col gap-2 max-h-64 overflow-y-auto'</span>)</span>
<span id="cb150-10">    )</span></code></pre></div></div>
<p>:::</p>
<div id="a5483063" class="cell" data-time_run="2026-01-22T00:42:27.709041+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb151" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb151-1">prev(Div(</span>
<span id="cb151-2">    Div(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'content'</span>)(</span>
<span id="cb151-3">        display_dialogs({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'userid'</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'current_dialog'</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">11</span>})</span>
<span id="cb151-4">    )</span>
<span id="cb151-5">))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<iframe srcdoc=" <!doctype html>
 <html>
   <head>
     <title>FastHTML page</title>
     <link rel=&quot;canonical&quot; href=&quot;https://testserver/_WYKxlDFyRQWPOl1fhn8wFA&quot;>
     <meta charset=&quot;utf-8&quot;>
     <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, viewport-fit=cover&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js&quot; defer></script><script type=&quot;module&quot;>import { marked } from &quot;https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js&quot;;
proc_htmx('.marked', e => e.innerHTML = marked.parse(e.textContent));</script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css&quot; media=&quot;(prefers-color-scheme: dark)&quot;>
     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css&quot; media=&quot;(prefers-color-scheme: light)&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js&quot;></script><script src=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js&quot;></script>     <link rel=&quot;stylesheet&quot; href=&quot;https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css&quot;>
<script src=&quot;https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js&quot;></script><script type=&quot;module&quot;>
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted=&quot;yes&quot;])'});
htmx.onLoad(hljs.highlightAll);</script><script>
    function sendmsg() {
        window.parent.postMessage({height: document.documentElement.offsetHeight}, '*');
    }
    window.onload = function() {
        sendmsg();
        document.body.addEventListener('htmx:afterSettle',    sendmsg);
        document.body.addEventListener('htmx:wsAfterMessage', sendmsg);
    };</script>   </head>
   <body>
     <div>
       <div id=&quot;content&quot;>
         <div class=&quot;flex flex-col gap-2 max-w-xl&quot;>
           <div class=&quot;flex items-center justify-between gap-4&quot;>
             <h1 class=&quot;text-2xl font-bold&quot; id=&quot;all-dialogs-title&quot;>所有对话</h1>
<form hx-post=&quot;/restore_session&quot; hx-target=&quot;#alert-box&quot; class=&quot;flex items-end gap-2&quot; id=&quot;restore-form&quot;>               <div>
<label for=&quot;restore_code&quot; class=&quot;label mb-2&quot;>Restore Code · provocative-lori-of-acceptance</label>                 <input type=&quot;text&quot; name=&quot;restore_code&quot; placeholder=&quot;Enter restore code...&quot; class=&quot;input &quot;>
               </div>
<button type=&quot;submit&quot; class=&quot;btn &quot;>Submit</button></form>           </div>
           <div id=&quot;alert-box&quot;></div>
           <div class=&quot;card p-4 hover:bg-gray-100 cursor-pointer border-2 border-dashed flex flex-row items-center gap-2&quot; hx-post=&quot;/create_dialog&quot; hx-target=&quot;#content&quot;>
➕<span id=&quot;new-dialog-text&quot;>新对话</span>           </div>
           <div class=&quot;flex flex-col gap-2 max-h-64 overflow-y-auto&quot;>
             <div id=&quot;dialog-11&quot; class=&quot;card p-4 hover:bg-gray-100 flex flex-row justify-between items-center&quot;>
<span hx-get=&quot;/dialog?dnum=1&quot; hx-target=&quot;#content&quot; class=&quot;cursor-pointer&quot;>💬 gleaming-tortoise</span><button hx-post=&quot;/delete_dialog?dnum=1&quot; hx-swap=&quot;delete&quot; hx-target=&quot;#dialog-11&quot; class=&quot;btn-destructive &quot;>Delete</button>             </div>
           </div>
         </div>
       </div>
     </div>
   </body>
 </html>
" style="width: 100%; height: auto; border: none;" onload="{
        let frame = this;
        window.addEventListener('message', function(e) {
            if (e.source !== frame.contentWindow) return; // Only proceed if the message is from this iframe
            if (e.data.height) frame.style.height = (e.data.height+1) + 'px';
        }, false);
    }" allow="accelerometer; autoplay; camera; clipboard-read; clipboard-write; display-capture; encrypted-media; fullscreen; gamepad; geolocation; gyroscope; hid; identity-credentials-get; idle-detection; magnetometer; microphone; midi; payment; picture-in-picture; publickey-credentials-get; screen-wake-lock; serial; usb; web-share; xr-spatial-tracking"></iframe> 
</div>
</div>
</section>
<section id="main-page" class="level3">
<h3 class="anchored" data-anchor-id="main-page">Main Page</h3>
<p>::: {#886bc7d5 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:42:30.692188+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb152" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb152-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span></span>
<span id="cb152-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> toggle_lang(session):</span>
<span id="cb152-3">    lang <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'zh'</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> session.get(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'lang'</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'en'</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'en'</span></span>
<span id="cb152-4">    current_lang.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">set</span>(lang)</span>
<span id="cb152-5">    session[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'lang'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> lang</span>
<span id="cb152-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> (</span>
<span id="cb152-7">        H2(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'solveit_lite'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'title'</span>, hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'true'</span>),</span>
<span id="cb152-8">        Button(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'all_dialogs'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'dialogs-btn'</span>, hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>display_dialogs, hx_target<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#content'</span>, var<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'secondary'</span>, hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'true'</span>),</span>
<span id="cb152-9">        Span(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'code'</span>), hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'innerHTML:#code-tab'</span>),</span>
<span id="cb152-10">        Span(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'prompt'</span>), hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'innerHTML:#qry-tab'</span>),</span>
<span id="cb152-11">        Span(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'note'</span>), hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'innerHTML:#note-tab'</span>),</span>
<span id="cb152-12">        Div(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'editor'</span>, hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'true'</span>),</span>
<span id="cb152-13">        Footer(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'footer'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'footer'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'text-sm text-gray-400'</span>, hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'true'</span>),</span>
<span id="cb152-14">        RestoreForm(session, hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'true'</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'restore-form'</span>),</span>
<span id="cb152-15">        H1(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'all_dialogs'</span>), cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'text-2xl font-bold'</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'all-dialogs-title'</span>, hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'true'</span>),</span>
<span id="cb152-16">        Span(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'new_dialog'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'new-dialog-text'</span>, hx_swap_oob<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'true'</span>)</span>
<span id="cb152-17">    )</span></code></pre></div></div>
<p>:::</p>
<p>This route allows users to switch between Chinese and English with OOB swaps to update all translatable text across the page simultaneously.</p>
<p>::: {#e98d1f46 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’ time_run=‘2026-01-22T00:42:32.887451+00:00’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb153" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb153-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@rt</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'/main'</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> insolveit <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'/'</span>)</span>
<span id="cb153-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> main(session):</span>
<span id="cb153-3">    setsession(session)</span>
<span id="cb153-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> Div(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'body'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'card p-8 max-w-4xl mx-auto my-4'</span>)(</span>
<span id="cb153-5">        Header(cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'flex justify-between items-center'</span>)(H2(</span>
<span id="cb153-6">            t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'solveit_lite'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'title'</span>), </span>
<span id="cb153-7">            Span(</span>
<span id="cb153-8">                Button(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'🌐'</span>, var<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'secondary'</span>, hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>toggle_lang, hx_swap<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'none'</span>), </span>
<span id="cb153-9">                Button(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'all_dialogs'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'dialogs-btn'</span>, hx_post<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>display_dialogs, hx_target<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'#content'</span>, var<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'secondary'</span>)</span>
<span id="cb153-10">            )</span>
<span id="cb153-11">        ),</span>
<span id="cb153-12">        Section(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'content'</span>)(</span>
<span id="cb153-13">            current_dialog(session)</span>
<span id="cb153-14">        ),</span>
<span id="cb153-15">        Footer(t(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'footer'</span>), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'footer'</span>, cls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'text-sm text-gray-400'</span>)</span>
<span id="cb153-16">    )</span></code></pre></div></div>
<p>:::</p>
<div id="fe1e1311" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb154" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb154-1">prev(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'/main'</span>)</span></code></pre></div></div>
</div>
<p><img src="https://forbo7.github.io/forblog/images/31_solveit_in_solveit/8.png" class="img-fluid"></p>
</section>
<section id="deploy" class="level3">
<h3 class="anchored" data-anchor-id="deploy">Deploy</h3>
<p>::: {#b05651d9 .cell 0=‘e’ 1=‘x’ 2=‘p’ 3=‘o’ 4=‘r’ 5=‘t’}</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb155" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb155-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> insolveit: serve()</span></code></pre></div></div>
<p>:::</p>
<div id="ce0a150b" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb156" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb156-1">Path(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'requirements.txt'</span>).write_text(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'''</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\</span></span>
<span id="cb156-2"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">python-fasthtml</span></span>
<span id="cb156-3"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">lisette</span></span>
<span id="cb156-4"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">coolname</span></span>
<span id="cb156-5"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">ipython</span></span>
<span id="cb156-6"><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'''</span>)</span>
<span id="cb156-7"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>cat requirements.txt</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>python-fasthtml
lisette
coolname
ipython</code></pre>
</div>
</div>
<div id="81c5cb9a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb158" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb158-1">Path(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'.plash'</span>).write_text(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'export PLASH_APP_NAME=solveit-lite-unofficial'</span>)</span>
<span id="cb158-2"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span>cat .plash</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>export PLASH_APP_NAME=solveit-lite-unofficial</code></pre>
</div>
</div>
<div id="074192d9" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb160" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb160-1">Path(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'plash.env'</span>).write_text(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'export MOONSHOT_API_KEY=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>os<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>environ<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>get(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MOONSHOT_API_KEY'</span>)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>75</code></pre>
</div>
</div>
<div id="8fc1ace6" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb162" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb162-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> plash_cli <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pc</span>
<span id="cb162-2">pc.deploy()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="0">
<pre data-code-line-numbers=""><code>'https://solveit-lite-unofficial.pla.sh'</code></pre>
</div>
</div>
<div id="e366368c" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb164" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb164-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(pc.logs())</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>Build Start Time: 2026-01-16 01:30:30.917195+00:00
Step 1/14 : FROM plash:latest
 ---&gt; 8c65e51fa2d2
Step 2/14 : ARG USER_UID=1000
 ---&gt; Using cache
 ---&gt; 781580c8e262
Step 3/14 : ARG USER_GID=1000
 ---&gt; Using cache
 ---&gt; dcf3956b8c50
Step 4/14 : RUN groupadd -g $USER_GID plash &amp;&amp; useradd -u $USER_UID -g $USER_GID -m plash
 ---&gt; Using cache
 ---&gt; fe019dc49177
Step 5/14 : ENV PLASH_PRODUCTION=1
 ---&gt; Using cache
 ---&gt; a86e28497fc0
Step 6/14 : COPY .dockerignore setup.sh* ./
 ---&gt; Using cache
 ---&gt; 786f3c3d2c09
Step 7/14 : RUN if [ -f ./setup.sh ]; then echo "Found setup.sh, executing..." &amp;&amp; chmod +x ./setup.sh &amp;&amp; ./setup.sh; fi
 ---&gt; Using cache
 ---&gt; 3f80b2a299d3
Step 8/14 : COPY .dockerignore requirements.txt* ./
 ---&gt; Using cache
 ---&gt; dea62d9dd70b
Step 9/14 : RUN if [ -f ./requirements.txt ]; then echo "Found requirements.txt, executing..." &amp;&amp; uv pip install -r ./requirements.txt --system; fi
 ---&gt; Using cache
 ---&gt; 241057bc8973
Step 10/14 : RUN chown -R plash:plash /app
 ---&gt; Using cache
 ---&gt; eb5b444c975f
Step 11/14 : USER plash
 ---&gt; Using cache
 ---&gt; d2eda950b2e1
Step 12/14 : ENV PATH="/home/plash/.local/bin:$PATH"
 ---&gt; Using cache
 ---&gt; 5631843ecbf7
Step 13/14 : EXPOSE 5001
 ---&gt; Using cache
 ---&gt; b1e69db470b1
Step 14/14 : ENTRYPOINT ["bash", "-c", "if [ -f ./plash.env ]; then . ./plash.env; fi &amp;&amp; python main.py"]
 ---&gt; Using cache
 ---&gt; 5ad4e58136f3
Successfully built 5ad4e58136f3
Successfully tagged 9d102cbb-e493-4ce7-9110-09dbf5c01851:latest

Build End Time: 2026-01-16 01:30:31.194696+00:00
</code></pre>
</div>
</div>
<div id="919d93ef" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb166" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb166-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(pc.logs(mode<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'app'</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>INFO:     Will watch for changes in these directories: ['/app']
INFO:     Uvicorn running on http://0.0.0.0:5001 (Press CTRL+C to quit)
INFO:     Started reloader process [1] using WatchFiles
Link: http://localhost:5001
INFO:     Started server process [14]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
</code></pre>
</div>
</div>
<div id="40589a55" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb168" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb168-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> httpx</span>
<span id="cb168-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(httpx.get(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'https://solveit-lite-unofficial.pla.sh'</span>).text)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code> &lt;!doctype html&gt;
 &lt;html&gt;
   &lt;head&gt;
     &lt;title&gt;FastHTML page&lt;/title&gt;
     &lt;link rel="canonical" href="https://solveit-lite-unofficial.pla.sh/"&gt;
     &lt;meta charset="utf-8"&gt;
     &lt;meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"&gt;
&lt;script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.7/dist/htmx.js"&gt;&lt;/script&gt;&lt;script src="https://cdn.jsdelivr.net/gh/answerdotai/fasthtml-js@1.0.12/fasthtml.js"&gt;&lt;/script&gt;&lt;script src="https://cdn.jsdelivr.net/gh/answerdotai/surreal@main/surreal.js"&gt;&lt;/script&gt;&lt;script src="https://cdn.jsdelivr.net/gh/gnat/css-scope-inline@main/script.js"&gt;&lt;/script&gt;&lt;script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"&gt;&lt;/script&gt;     &lt;link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/basecoat.cdn.min.css"&gt;
&lt;script src="https://cdn.jsdelivr.net/npm/basecoat-css@0.3.6/dist/js/all.min.js" defer&gt;&lt;/script&gt;&lt;script type="module"&gt;import { marked } from "https://cdn.jsdelivr.net/npm/marked/lib/marked.esm.js";
proc_htmx('.marked', e =&gt; e.innerHTML = marked.parse(e.textContent));&lt;/script&gt;     &lt;link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-dark.css" media="(prefers-color-scheme: dark)"&gt;
     &lt;link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/styles/atom-one-light.css" media="(prefers-color-scheme: light)"&gt;
&lt;script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/highlight.min.js"&gt;&lt;/script&gt;&lt;script src="https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.js"&gt;&lt;/script&gt;     &lt;link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/arronhunt/highlightjs-copy/dist/highlightjs-copy.min.css"&gt;
&lt;script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release/build/languages/python.min.js"&gt;&lt;/script&gt;&lt;script type="module"&gt;
hljs.addPlugin(new CopyButtonPlugin());
hljs.configure({'cssSelector': 'pre code:not([data-highlighted="yes"])'});
htmx.onLoad(hljs.highlightAll);&lt;/script&gt;   &lt;/head&gt;
   &lt;body&gt;
     &lt;div id="body" class="card p-8 max-w-4xl mx-auto my-4"&gt;
       &lt;header class="flex justify-between items-center"&gt;
         &lt;h2 id="title"&gt;solveit-lite&lt;/h2&gt;
&lt;span&gt;&lt;button hx-post="/toggle_lang" hx-swap="none" class="btn-secondary "&gt;🌐&lt;/button&gt;&lt;button hx-post="/display_dialogs" hx-target="#content" id="dialogs-btn" class="btn-secondary " name="dialogs-btn"&gt;All Dialogs&lt;/button&gt;&lt;/span&gt;       &lt;/header&gt;
       &lt;section id="content"&gt;
         &lt;div class="tabs w-full"&gt;
           &lt;h1 class="text-2xl font-bold" id="dname" hx-get="/edit_dname" hx-target="#dname" hx-swap="outerHTML"&gt;intrepid-turaco&lt;/h1&gt;
           &lt;div id="msgs" class="p-8 max-h-96 overflow-y-auto" hx-get="/load_messages" hx-trigger="load"&gt;&lt;/div&gt;
           &lt;nav class="w-full " role="tablist" id="tabbar"&gt;
&lt;button type="button" role="tab" hx-post="/code_editor" hx-swap="innerHTML" hx-target="#editor" id="code-tab" name="code-tab"&gt;Code&lt;/button&gt;&lt;button type="button" role="tab" hx-post="/llm_editor" hx-swap="innerHTML" hx-target="#editor" id="qry-tab" name="qry-tab"&gt;Prompt&lt;/button&gt;&lt;button type="button" role="tab" hx-post="/note_editor" hx-swap="innerHTML" hx-target="#editor" id="note-tab" name="note-tab"&gt;Note&lt;/button&gt;           &lt;/nav&gt;
           &lt;div id="editor"&gt;&lt;/div&gt;
         &lt;/div&gt;
       &lt;/section&gt;
       &lt;footer id="footer" class="text-sm text-gray-400"&gt;Crafted with FastHTML&lt;/footer&gt;
     &lt;/div&gt;
   &lt;/body&gt;
 &lt;/html&gt;
</code></pre>
</div>
</div>
<hr>
<p>If you have any comments, questions, suggestions, feedback, criticisms, or corrections, please do post them down in the comment section below!</p>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Agents</category>
  <category>Approaching AI</category>
  <category>LLMs</category>
  <category>SolveIt</category>
  <category>Programming</category>
  <category>HTML</category>
  <guid>https://forbo7.github.io/forblog/posts/31_solveit_in_solveit.html</guid>
  <pubDate>Thu, 22 Jan 2026 00:00:00 GMT</pubDate>
  <media:content url="https://forbo7.github.io/forblog/images/31_solveit_in_solveit/thumbnail.png" medium="image" type="image/png" height="115" width="144"/>
</item>
<item>
  <title>Translating SolveIt Dialogues</title>
  <dc:creator>Salman Naqvi</dc:creator>
  <link>https://forbo7.github.io/forblog/posts/30_translating_solveit_dialogues.html</link>
  <description><![CDATA[ 




<p><img src="https://forbo7.github.io/forblog/images/30_translating_solveit_dialogues/thumbnail.png" class="img-fluid"></p>
<section id="introduction" class="level2">
<h2 class="anchored" data-anchor-id="introduction">Introduction</h2>
<p>In this notebook I’ll be demonstrating how one can update messages in SolveIt dialogues and do further work with them. At the same time also demonstrating how SolveIt dialogue messages can be translated with a LLM.</p>
<p>I’m currently teaching myself Chinese, and I’ve found to learn a language, one has to use the language. So I make the LLM respond in Chinese.</p>
<p>I’ll be using <a href="https://lisette.answer.ai/">lisette</a> for working with the LLM, DeepSeek as the model, and <a href="https://answerdotai.github.io/dialoghelper/">dialoghelper</a> to process the dialogue messages.</p>
</section>
<section id="sample-dialogue" class="level2">
<h2 class="anchored" data-anchor-id="sample-dialogue">Sample Dialogue</h2>
<p>I’ll create a rough, short dialogue that I can work upon.</p>
<blockquote class="blockquote">
<p>You’ll see that the English translations are already appended. See the SolveIt dialogue <a href="https://share.solve.it.com/d/24bf30f133c01f37feae1a1e22e27bcc">here</a>.</p>
</blockquote>
<p>Hey there, who are you?</p>
<section id="reply" class="level5">
<h5 class="anchored" data-anchor-id="reply">🤖Reply🤖<!-- SOLVEIT_SEPARATOR_7f3a9b2c --></h5>
<p>🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠</p>
<p>你好！我是 solveit，一个学习助手。我可以帮你学习各种各样的东西——数学、编程、写作，或者别的什么。</p>
<p>你想学什么呢？你对什么感兴趣？告诉我一点儿关于你自己的情况吧，这样我可以更好地帮助你。</p>
<hr>
<p>Hello! I’m solveit, a learning assistant. I can help you learn all sorts of things—math, programming, writing, or anything else.</p>
<p>What would you like to learn? What are you interested in? Tell me a little about yourself so I can help you better.</p>
<hr>
<p>Hello! I’m solveit, a learning assistant. I can help you learn all sorts of things—math, programming, writing, or anything else.</p>
<p>What would you like to learn? What are you interested in? Tell me a little about yourself so I can help you better.</p>
<p>Let me flip it around: what do <em>you</em> want to study? What’re <em>you</em> currently interested in?</p>
</section>
<section id="reply-1" class="level5">
<h5 class="anchored" data-anchor-id="reply-1">🤖Reply🤖<!-- SOLVEIT_SEPARATOR_7f3a9b2c --></h5>
<p>哈哈，这个问题很有意思！</p>
<p>其实我对很多东西都感兴趣。最近我特别喜欢思考这些问题：</p>
<ul>
<li>人们怎么学习新东西？什么方法最有效？</li>
<li>复杂的问题怎么分解成简单的部分？</li>
<li>不同领域的知识怎么连接起来？</li>
</ul>
<p>但是，我在这儿是为了帮助你学习和探索。你的好奇心和兴趣才是最重要的！</p>
<p>所以，咱们可以一起探索一个你感兴趣的话题。你现在想学什么？或者你正在做什么项目？</p>
<hr>
<p>Haha, that’s a really interesting question!</p>
<p>Actually, I’m interested in a lot of things. Lately, I’ve been particularly fond of thinking about these questions:</p>
<ul>
<li>How do people learn new things? What methods are most effective?</li>
<li>How can complex problems be broken down into simpler parts?</li>
<li>How is knowledge from different fields connected?</li>
</ul>
<p>However, I’m here to help <em>you</em> learn and explore. Your curiosity and interests are what matter most!</p>
<p>So, we can explore a topic you’re interested in together. What would you like to learn right now? Or are you working on any projects?</p>
</section>
</section>
<section id="translation" class="level2">
<h2 class="anchored" data-anchor-id="translation">Translation</h2>
<div id="1dda5de7" class="cell" data-time_run="2025-12-05T03:00:23.374270+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> dialoghelper <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span></span></code></pre></div></div>
</div>
<div id="6a74d977" class="cell" data-time_run="2025-12-05T02:27:14.303180+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1">?find_msgs</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div class="ansi-escaped-output">
<pre><span class="ansi-red-fg">Signature:</span>
find_msgs(
    re_pattern: str = <span class="ansi-yellow-fg">''</span>,
    msg_type: str = <span style="font-weight:bold;color:rgb(0,135,0)">None</span>,
    limit: int = <span style="font-weight:bold;color:rgb(0,135,0)">None</span>,
    include_output: bool = <span style="font-weight:bold;color:rgb(0,135,0)">True</span>,
    dname: str = <span class="ansi-yellow-fg">''</span>,
)
<span class="ansi-red-fg">Docstring:</span> Find `list[dict]` of messages in current specific dialog that contain the given information. To refer to a message found later, use its `id` field.
<span class="ansi-red-fg">File:</span>      /usr/local/lib/python3.12/site-packages/dialoghelper/core.py
<span class="ansi-red-fg">Type:</span>      function</pre>
</div>
</div>
</div>
<p>We can use <code>find_msgs</code> to filter out those message types that are prompts.</p>
<div id="fe19e3d1" class="cell" data-time_run="2025-12-05T02:27:16.279909+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1">o <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> find_msgs(msg_type<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'prompt'</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> o[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre data-code-line-numbers=""><code>{'id': '_4dcda3fa',
 'input_tokens': 10,
 'output_tokens': 94,
 'time_run': '',
 'is_exported': False,
 'skipped': False,
 'hidden': False,
 'bookmark': None,
 'i_collapsed': False,
 'o_collapsed': False,
 'heading_collapsed': False,
 'i_clamp': False,
 'o_clamp': False,
 'pinned': False,
 'use_thinking': True,
 'attachments': [],
 'oob': None,
 'run': None,
 'scroll': False,
 'order': 3,
 'content': 'Hey there, who are you?',
 'output': '🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠\n\n你好！我是 solveit，一个学习助手。我可以帮你学习各种各样的东西——数学、编程、写作，或者别的什么。\n\n你想学什么呢？你对什么感兴趣？告诉我一点儿关于你自己的情况吧，这样我可以更好地帮助你。',
 'msg_type': 'prompt'}</code></pre>
</div>
</div>
<div id="82fe760e" class="cell" data-time_run="2025-12-05T02:27:19.558714+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1">o[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'output'</span>]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre data-code-line-numbers=""><code>'🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠\n\n你好！我是 solveit，一个学习助手。我可以帮你学习各种各样的东西——数学、编程、写作，或者别的什么。\n\n你想学什么呢？你对什么感兴趣？告诉我一点儿关于你自己的情况吧，这样我可以更好地帮助你。'</code></pre>
</div>
</div>
<p>And then when we are iterating through all the prompt messages we can fetch the respective message ID and update it using <code>update_msg</code>.</p>
<div id="6ab909d1" class="cell" data-time_run="2025-12-05T02:27:23.443791+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1">?update_msg</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div class="ansi-escaped-output">
<pre><span class="ansi-red-fg">Signature:</span>
update_msg(
    msgid: str = <span style="font-weight:bold;color:rgb(0,135,0)">None</span>,
    msg: Optional[Dict] = <span style="font-weight:bold;color:rgb(0,135,0)">None</span>,
    dname: str = <span class="ansi-yellow-fg">''</span>,
    *,
    content: str | <span style="font-weight:bold;color:rgb(0,135,0)">None</span> = <span style="font-weight:bold;color:rgb(0,135,0)">None</span>,
    msg_type: str | <span style="font-weight:bold;color:rgb(0,135,0)">None</span> = <span style="font-weight:bold;color:rgb(0,135,0)">None</span>,
    output: str | <span style="font-weight:bold;color:rgb(0,135,0)">None</span> = <span style="font-weight:bold;color:rgb(0,135,0)">None</span>,
    time_run: str | <span style="font-weight:bold;color:rgb(0,135,0)">None</span> = <span style="font-weight:bold;color:rgb(0,135,0)">None</span>,
    is_exported: int | <span style="font-weight:bold;color:rgb(0,135,0)">None</span> = <span style="font-weight:bold;color:rgb(0,135,0)">None</span>,
    skipped: int | <span style="font-weight:bold;color:rgb(0,135,0)">None</span> = <span style="font-weight:bold;color:rgb(0,135,0)">None</span>,
    i_collapsed: int | <span style="font-weight:bold;color:rgb(0,135,0)">None</span> = <span style="font-weight:bold;color:rgb(0,135,0)">None</span>,
    o_collapsed: int | <span style="font-weight:bold;color:rgb(0,135,0)">None</span> = <span style="font-weight:bold;color:rgb(0,135,0)">None</span>,
    heading_collapsed: int | <span style="font-weight:bold;color:rgb(0,135,0)">None</span> = <span style="font-weight:bold;color:rgb(0,135,0)">None</span>,
    pinned: int | <span style="font-weight:bold;color:rgb(0,135,0)">None</span> = <span style="font-weight:bold;color:rgb(0,135,0)">None</span>,
)
<span class="ansi-red-fg">Docstring:</span>
Update an existing message. Provide either `msg` OR field key/values to update.
- Use `content` param to update contents.
- Only include parameters to update--missing ones will be left unchanged.
<span class="ansi-red-fg">File:</span>      /usr/local/lib/python3.12/site-packages/dialoghelper/core.py
<span class="ansi-red-fg">Type:</span>      function</pre>
</div>
</div>
</div>
<p>I’ll be formatting the new updated prompt output as <code>original + '\n\n---\n\n' + translated</code>.</p>
<p>In a nutshell, the core loop is:</p>
<ol type="1">
<li>Fetch a prompt message.</li>
<li>Access the output content of that message.</li>
<li>Translate.</li>
<li>Reformat output content</li>
<li>Update the respective message.</li>
</ol>
<p>I’ll begin with a single example.</p>
<div id="ab787b9d" class="cell" data-time_run="2025-12-05T02:32:58.835233+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> lisette.core <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span></span>
<span id="cb8-2">sys_prmpt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"You'll receive a series of messages that are responses in a dialogue. I need you to aptly translate those responses to English, whilst maintaining the same tone/style and minimal loss of information. If you encoutner any brain emojies, skip them. Do not re-output the original message."</span></span>
<span id="cb8-3">chat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Chat(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'deepseek/deepseek-chat'</span>, hist<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[sys_prmpt])<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> chat</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre data-code-line-numbers=""><code>&lt;lisette.core.Chat at 0x7da9f8871160&gt;</code></pre>
</div>
</div>
<div id="5b7ba778" class="cell" data-time_run="2025-12-05T02:33:07.421033+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1">res <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chat(o[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'output'</span>])</span>
<span id="cb10-2">display(res)</span></code></pre></div></div>
<div class="cell-output cell-output-display cell-output-markdown">
<p>Hello! I’m solveit, a learning assistant. I can help you learn all sorts of things—math, programming, writing, or anything else.</p>
<p>What would you like to learn? What are you interested in? Tell me a little about yourself so I can help you better.</p>
<details>
<ul>
<li>id: <code>22a761da-f8a1-43a4-be6f-06a54db8ca0f</code></li>
<li>model: <code>deepseek-chat</code></li>
<li>finish_reason: <code>stop</code></li>
<li>usage: <code>Usage(completion_tokens=57, prompt_tokens=155, total_tokens=212, completion_tokens_details=None, prompt_tokens_details=PromptTokensDetailsWrapper(audio_tokens=None, cached_tokens=64, text_tokens=None, image_tokens=None), prompt_cache_hit_tokens=64, prompt_cache_miss_tokens=91)</code></li>
</ul>
</details>
</div>
</div>
<div id="8faa61ce" class="cell" data-time_run="2025-12-05T02:33:17.480820+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1">display(chat(o[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'output'</span>]))</span></code></pre></div></div>
<div class="cell-output cell-output-display cell-output-markdown">
<p>Haha, that’s a very interesting question!</p>
<p>Actually, I’m interested in a lot of things. Lately, I’ve been particularly fond of pondering these questions:</p>
<ul>
<li>How do people learn new things? What methods are most effective?</li>
<li>How can complex problems be broken down into simpler parts?</li>
<li>How is knowledge from different fields connected?</li>
</ul>
<p>However, I’m here to help <em>you</em> learn and explore. Your curiosity and interests are what matter most!</p>
<p>So, we can explore a topic you’re interested in together. What would you like to learn right now? Or are you working on any projects?</p>
<details>
<ul>
<li>id: <code>cb9c2af2-e7ed-48cf-ae27-dbf56bd1684c</code></li>
<li>model: <code>deepseek-chat</code></li>
<li>finish_reason: <code>stop</code></li>
<li>usage: <code>Usage(completion_tokens=123, prompt_tokens=300, total_tokens=423, completion_tokens_details=None, prompt_tokens_details=PromptTokensDetailsWrapper(audio_tokens=None, cached_tokens=128, text_tokens=None, image_tokens=None), prompt_cache_hit_tokens=128, prompt_cache_miss_tokens=172)</code></li>
</ul>
</details>
</div>
</div>
<p>So that’s how the translations look. Let’s now update the messages themselves.</p>
<div id="e7fd3bae" class="cell" data-time_run="2025-12-05T02:33:28.427891+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1">??update_msg</span></code></pre></div></div>
<div class="cell-output cell-output-display cell-output-markdown">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1"><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">@delegates</span>(_umsg)</span>
<span id="cb13-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> update_msg(</span>
<span id="cb13-3">    msgid:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># id of message to update (if None, uses current message)</span></span>
<span id="cb13-4">    msg:Optional[Dict]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Dictionary of field keys/values to update</span></span>
<span id="cb13-5">    dname:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">''</span>, <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Running dialog to get info for; defaults to current dialog</span></span>
<span id="cb13-6">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs):</span>
<span id="cb13-7">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"""Update an existing message. Provide either `msg` OR field key/values to update.</span></span>
<span id="cb13-8"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    - Use `content` param to update contents.</span></span>
<span id="cb13-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">    - Only include parameters to update--missing ones will be left unchanged."""</span></span>
<span id="cb13-10">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> msgid <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> msg: <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">TypeError</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"update_msg needs either a dict message or `msgid=`"</span>)</span>
<span id="cb13-11">    res <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> call_endp(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'update_msg_'</span>, dname, msgid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>msgid, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs)</span>
<span id="cb13-12">    set_var(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'__msg_id'</span>, res)</span>
<span id="cb13-13">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> res</span></code></pre></div></div>
<p><strong>File:</strong> <code>/usr/local/lib/python3.12/site-packages/dialoghelper/core.py</code></p>
</div>
</div>
<div id="17fb74cb" class="cell" data-time_run="2025-12-05T02:33:30.090629+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1">trans <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> res.choices[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].message.content<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> trans</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre data-code-line-numbers=""><code>"Hello! I'm solveit, a learning assistant. I can help you learn all sorts of things—math, programming, writing, or anything else.\n\nWhat would you like to learn? What are you interested in? Tell me a little about yourself so I can help you better."</code></pre>
</div>
</div>
<div id="bfceadd8" class="cell" data-time_run="2025-12-05T02:33:31.864824+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1">new_out <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> o[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'output'</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">---</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>trans<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> new_out</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre data-code-line-numbers=""><code>"🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠\n\n你好！我是 solveit，一个学习助手。我可以帮你学习各种各样的东西——数学、编程、写作，或者别的什么。\n\n你想学什么呢？你对什么感兴趣？告诉我一点儿关于你自己的情况吧，这样我可以更好地帮助你。\n\n---\n\nHello! I'm solveit, a learning assistant. I can help you learn all sorts of things—math, programming, writing, or anything else.\n\nWhat would you like to learn? What are you interested in? Tell me a little about yourself so I can help you better."</code></pre>
</div>
</div>
<div id="cec13353" class="cell" data-time_run="2025-12-05T02:33:38.659461+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb18" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1">update_msg(msgid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>o[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'id'</span>], output<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>new_out)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre data-code-line-numbers=""><code>'_4dcda3fa'</code></pre>
</div>
</div>
<div id="a4e3261c" class="cell" data-time_run="2025-12-05T02:38:45.742724+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb20" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb20-1">o[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre data-code-line-numbers=""><code>{'id': '_4dcda3fa',
 'input_tokens': 10,
 'output_tokens': 94,
 'time_run': '',
 'is_exported': False,
 'skipped': False,
 'hidden': False,
 'bookmark': None,
 'i_collapsed': False,
 'o_collapsed': False,
 'heading_collapsed': False,
 'i_clamp': False,
 'o_clamp': False,
 'pinned': False,
 'use_thinking': True,
 'attachments': [],
 'oob': None,
 'run': None,
 'scroll': False,
 'order': 3,
 'content': 'Hey there, who are you?',
 'output': '🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠🧠\n\n你好！我是 solveit，一个学习助手。我可以帮你学习各种各样的东西——数学、编程、写作，或者别的什么。\n\n你想学什么呢？你对什么感兴趣？告诉我一点儿关于你自己的情况吧，这样我可以更好地帮助你。',
 'msg_type': 'prompt'}</code></pre>
</div>
</div>
<p>The message has been updated! <a href="javascript:document.getElementById('_4dcda3fa').scrollIntoView({behavior: 'smooth'})">Click here</a> to jump to it and see the update.</p>
<p>Now we can package everything up into a loop.</p>
<div id="819b2f3f" class="cell" data-time_run="2025-12-05T02:49:25.924848+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb22" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb22-1">chat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Chat(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'deepseek/deepseek-chat'</span>, hist<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[sys_prmpt])</span>
<span id="cb22-2">outs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> find_msgs(msg_type<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'prompt'</span>)</span>
<span id="cb22-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> o <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> outs:</span>
<span id="cb22-4">    r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> chat(o[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'output'</span>])</span>
<span id="cb22-5">    trans <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> r.choices[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].message.content</span>
<span id="cb22-6">    new_o <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> o[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'output'</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">---</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\n\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>trans</span>
<span id="cb22-7">    update_msg(msgid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>o[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'id'</span>], output<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>new_o)</span></code></pre></div></div>
</div>
<p>Some areas for improvement: - [ ] The reformatted output includes collapsable/folding blocks - [ ] Figure out how to use <a href="https://github.com/AnswerDotAI/fastprogress">fastprogress</a> view translation progress.</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>And it’s as simple as that!</p>
<p>If you have any comments, questions, suggestions, feedback, criticisms, or corrections, please do post them down in the comment section below!</p>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>SolveIt</category>
  <guid>https://forbo7.github.io/forblog/posts/30_translating_solveit_dialogues.html</guid>
  <pubDate>Sun, 07 Dec 2025 00:00:00 GMT</pubDate>
  <media:content url="https://forbo7.github.io/forblog/images/30_translating_solveit_dialogues/thumbnail.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>Let’s build an AI model</title>
  <dc:creator>Salman Naqvi</dc:creator>
  <link>https://forbo7.github.io/forblog/posts/29_lets_build_an_ai_model.html</link>
  <description><![CDATA[ 




<p><img src="https://forbo7.github.io/forblog/images/29_lets_build_an_ai_model/thumbnail.png" class="img-fluid"></p>
<div class="callout callout-style-simple callout-note">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>This notebook is a remix of <a href="https://www.kaggle.com/code/jhoward/is-it-a-bird-creating-a-model-from-your-own-data">fastai Lesson 1’s ‘Is it a Bird’ notebook</a> by <a href="https://solve.it.com/#im-jeremy-howard-from-fastai">Jeremy Howard</a>, as a way to practice the writing techniques taught in the <a href="https://solve.it.com/">SolveIt course</a>, led by Jeremy Howard and <a href="https://www.johnowhitaker.com/">Johnothan Whitaker</a>. SolveIt is also a brilliant problem-solving framework and interactive platform, that puts you in control–not the LLM.</p>
</div>
</div>
</div>
<section id="the-requirement" class="level2">
<h2 class="anchored" data-anchor-id="the-requirement">The Requirement</h2>
<p>The bar is low. It looks complicated, but it’s not. This is the reality to get started making your own AI models:</p>
<p><strong>Math:</strong> None. Really.</p>
<p><strong>Data:</strong> You can go miles with only 50 items.</p>
<p><strong>Computing power:</strong> You can get state of the art computing for free.</p>
<p><strong>Experience:</strong> If you can write basic code and understand what a function is, you’re ready.</p>
<p>Just kidding–these aren’t the real requirements. The real requirement is being okay with not understanding everything immediately. You’ll learn by doing first, understanding later.</p>
<p>When you play soccer, do you sit in a physics classroom or starting kicking a ball?</p>
</section>
<section id="lets-kick-the-ball" class="level2">
<h2 class="anchored" data-anchor-id="lets-kick-the-ball">Let’s Kick the Ball</h2>
<p>To get started:</p>
<ul>
<li>Head to <a href="kaggle.com">Kaggle</a>, sign up, and verify your phone number (that’s how you get access to fancy GPUs)</li>
<li>Create a notebook</li>
<li>Then in the first cell, run <code>!uv pip install ddg</code>–this is just setting up the equipment in the soccer pitch</li>
</ul>
<p>In 2015, this XKCD comic made a joke: distinguishing birds from non-birds in photos was “nearly impossible” for computers. Everyone laughed because it was obvioulsy true.</p>
<p><img src="https://imgs.xkcd.com/comics/tasks.png" class="img-fluid"></p>
<p>Let’s build that exact system, in minutes. If you think it’ll be hard, it’ll be hard. If you think it’ll be easy, it’ll be easy.</p>
<p>We’ll need to:</p>
<ol type="1">
<li>Get some data</li>
<li>Process the data</li>
<li>Fine-tune an AI model</li>
<li>Use the model</li>
</ol>
<div id="c7441058" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span> uv pip install ddgs</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<div class="ansi-escaped-output">
<pre>Using Python 3.11.13 environment at: /usr

Resolved <span style="font-weight:bold;opacity:0.7">17 packages</span> in 370ms                                        

Prepared <span style="font-weight:bold;opacity:0.7">4 packages</span> in 229ms                                             

Uninstalled <span style="font-weight:bold;opacity:0.7">1 package</span> in 21ms

Installed <span style="font-weight:bold;opacity:0.7">4 packages</span> in 11ms                                

 <span class="ansi-green-fg">+</span> <span class="ansi-bold">ddgs</span>==9.8.0

 <span class="ansi-red-fg">-</span> <span class="ansi-bold">lxml</span>==5.4.0

 <span class="ansi-green-fg">+</span> <span class="ansi-bold">lxml</span>==6.0.2

 <span class="ansi-green-fg">+</span> <span class="ansi-bold">primp</span>==0.15.0

 <span class="ansi-green-fg">+</span> <span class="ansi-bold">socksio</span>==1.0.0
</pre>
</div>
</div>
</div>
<div id="3b3a1319" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> logging</span>
<span id="cb2-2">logging.disable(logging.WARNING)</span></code></pre></div></div>
</div>
<section id="step-1-getting-some-images" class="level3">
<h3 class="anchored" data-anchor-id="step-1-getting-some-images">Step 1: Getting some Images</h3>
<p>We need some images to teach the model what’s a bird and what’s a first.</p>
<p>Rather than manually searching for photos by hand, let’s programmatically do it.</p>
<p>First, let’s search for a single photo to make sure our search works.</p>
<div id="605dee3e" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> ddgs <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> DDGS</span>
<span id="cb3-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fastcore.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">all</span> <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span></span>
<span id="cb3-3"></span>
<span id="cb3-4"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> search_images(keywords, max_images<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">200</span>):</span>
<span id="cb3-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> L(DDGS().images(keywords, max_results<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>max_images)).itemgot(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'image'</span>)</span>
<span id="cb3-6"></span>
<span id="cb3-7">urls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> search_images(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bird photos'</span>, max_images<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span></code></pre></div></div>
</div>
<p>Let’s download it and have a look.</p>
<div id="f2b62eb4" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb4" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fastdownload <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> download_url</span>
<span id="cb4-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fastai.vision.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">all</span> <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span></span>
<span id="cb4-3"></span>
<span id="cb4-4">download_url(urls[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bird.jpg'</span>, show_progress<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb4-5">im <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Image.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bird.jpg'</span>)</span>
<span id="cb4-6">im.to_thumb(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">256</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">256</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stderr">
<pre data-code-line-numbers=""><code>/usr/local/lib/python3.11/dist-packages/pydantic/_internal/_generate_schema.py:2249: UnsupportedFieldAttributeWarning: The 'repr' attribute with value False was provided to the `Field()` function, which has no effect in the context it was used. 'repr' is field-specific metadata, and can only be attached to a model field using `Annotated` metadata or by assignment. This may have happened because an `Annotated` type alias using the `type` statement was used, or if the `Field()` function was attached to a single member of a union type.
  warnings.warn(
/usr/local/lib/python3.11/dist-packages/pydantic/_internal/_generate_schema.py:2249: UnsupportedFieldAttributeWarning: The 'frozen' attribute with value True was provided to the `Field()` function, which has no effect in the context it was used. 'frozen' is field-specific metadata, and can only be attached to a model field using `Annotated` metadata or by assignment. This may have happened because an `Annotated` type alias using the `type` statement was used, or if the `Field()` function was attached to a single member of a union type.
  warnings.warn(</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="4">
<div>
<figure class="figure">
<p><img src="https://forbo7.github.io/forblog/posts/29_lets_build_an_ai_model_files/figure-html/cell-5-output-2.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>Now grab 200 bird photos and 200 forest photos (our ‘not bird’ category).</p>
<div id="4d133e8f" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb6" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1">searches <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'forest'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bird'</span></span>
<span id="cb6-2">path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Path(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bird_or_not'</span>)</span>
<span id="cb6-3"></span>
<span id="cb6-4"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> o <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> searches:</span>
<span id="cb6-5">    dest <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (path<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>o)</span>
<span id="cb6-6">    dest.mkdir(exist_ok<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, parents<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb6-7">    download_images(dest, urls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>search_images(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>o<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> photo'</span>))</span>
<span id="cb6-8">    resize_images(path<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>o, max_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">400</span>, dest<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>path<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>o)</span></code></pre></div></div>
</div>
</section>
<section id="step-2-create-a-datablock" class="level3">
<h3 class="anchored" data-anchor-id="step-2-create-a-datablock">Step 2: Create a DataBlock</h3>
<p>Here, we’ll be performing a bunch of processes on the data.</p>
<div id="4c008c10" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1">dls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataBlock(</span>
<span id="cb7-2">    blocks<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(ImageBlock, CategoryBlock), </span>
<span id="cb7-3">    get_items<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>get_image_files, </span>
<span id="cb7-4">    splitter<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>RandomSplitter(valid_pct<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, seed<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>),</span>
<span id="cb7-5">    get_y<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>parent_label,</span>
<span id="cb7-6">    item_tfms<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[Resize(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">192</span>, method<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'squish'</span>)]</span>
<span id="cb7-7">).dataloaders(path, bs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32</span>)</span>
<span id="cb7-8"></span>
<span id="cb7-9">dls.show_batch(max_n<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://forbo7.github.io/forblog/posts/29_lets_build_an_ai_model_files/figure-html/cell-7-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<p>What this means:</p>
<ul>
<li><strong>blocks</strong>: inputs are images, outputs are categories</li>
<li><strong>get_items</strong>: find all image files</li>
<li><strong>splitter</strong>: randomly hold out 20% for testing</li>
<li><strong>get_y</strong>: label comes from folder name (bird/forest)</li>
<li><strong>item_tfms</strong>: resize everything to 192×192</li>
</ul>
</section>
<section id="step-3-train" class="level3">
<h3 class="anchored" data-anchor-id="step-3-train">Step 3: Train</h3>
<div id="068fb871" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> vision_learner(dls, resnet18, metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>error_rate)</span>
<span id="cb8-2">learn.fine_tune(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stderr">
<pre data-code-line-numbers=""><code>Downloading: "https://download.pytorch.org/models/resnet18-f37072fd.pth" to /root/.cache/torch/hub/checkpoints/resnet18-f37072fd.pth
100%|██████████| 44.7M/44.7M [00:00&lt;00:00, 149MB/s] </code></pre>
</div>
<div class="cell-output cell-output-display">

<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 class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th">epoch</th>
<th data-quarto-table-cell-role="th">train_loss</th>
<th data-quarto-table-cell-role="th">valid_loss</th>
<th data-quarto-table-cell-role="th">error_rate</th>
<th data-quarto-table-cell-role="th">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>0.928233</td>
<td>0.830080</td>
<td>0.205128</td>
<td>00:10</td>
</tr>
</tbody>
</table>
</div>
<div class="cell-output cell-output-display">

<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 class="cell-output cell-output-display">
<table class="dataframe caption-top table table-sm table-striped small" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th">epoch</th>
<th data-quarto-table-cell-role="th">train_loss</th>
<th data-quarto-table-cell-role="th">valid_loss</th>
<th data-quarto-table-cell-role="th">error_rate</th>
<th data-quarto-table-cell-role="th">time</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>0.421934</td>
<td>0.592662</td>
<td>0.153846</td>
<td>00:14</td>
</tr>
<tr class="even">
<td>1</td>
<td>0.265431</td>
<td>0.519274</td>
<td>0.128205</td>
<td>00:14</td>
</tr>
<tr class="odd">
<td>2</td>
<td>0.191559</td>
<td>0.445995</td>
<td>0.102564</td>
<td>00:14</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>Done. You trained a model.</p>
</section>
<section id="step-4-use-the-model" class="level3">
<h3 class="anchored" data-anchor-id="step-4-use-the-model">Step 4: Use the Model</h3>
<div id="16e874e5" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1">im.to_thumb(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">256</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">256</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="11">
<div>
<figure class="figure">
<p><img src="https://forbo7.github.io/forblog/posts/29_lets_build_an_ai_model_files/figure-html/cell-9-output-1.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="f0b322a7" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1">is_bird,_,probs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> learn.predict(PILImage.create(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bird.jpg'</span>))</span>
<span id="cb11-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"This is a: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>is_bird<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">."</span>)</span>
<span id="cb11-3"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"Probability it's a bird: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>probs[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.4f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display">

<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 class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>This is a: bird.
Probability it's a bird: 1.0000</code></pre>
</div>
</div>
<p>That’s it. From joke to reality.</p>
</section>
</section>
<section id="what-just-happened" class="level2">
<h2 class="anchored" data-anchor-id="what-just-happened">What Just Happened?</h2>
<p><strong>Datasets and splits</strong></p>
<p>We used DuckDuckGo to find image URLs, then downloaded them. You created your very own dataset.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb13" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode py code-with-copy"><code class="sourceCode python"><span id="cb13-1">searches <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'forest'</span>,<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bird'</span></span>
<span id="cb13-2">path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Path(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bird_or_not'</span>)</span>
<span id="cb13-3"></span>
<span id="cb13-4"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> o <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> searches:</span>
<span id="cb13-5">    dest <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (path<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>o)</span>
<span id="cb13-6">    dest.mkdir(exist_ok<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, parents<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb13-7">    download_images(dest, urls<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>search_images(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>o<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;"> photo'</span>))</span>
<span id="cb13-8">    resize_images(path<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>o, max_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">400</span>, dest<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>path<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>o)</span></code></pre></div></div>
<p>Machine learning models need two things: data to learn from (training set) and data to test accuracy (validation set). We split our 400 images 80/20:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb14" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1">splitter<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>RandomSplitter(valid_pct<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.2</span>, seed<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">42</span>)</span></code></pre></div></div>
<p>The model never sees validation images during training. This tells us if it actually learned or just memorized.</p>
<p><strong>DataBlocks and DataLoaders</strong></p>
<p>A <code>DataBlock</code> is a block of data. It says “here’s how to handle my data”:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb15" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb15-1">DataBlock(</span>
<span id="cb15-2">    blocks<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>(ImageBlock, CategoryBlock),  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># what type of data</span></span>
<span id="cb15-3">    get_items<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>get_image_files,           <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># how to find it</span></span>
<span id="cb15-4">    splitter<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>RandomSplitter(...),        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># how to split it</span></span>
<span id="cb15-5">    get_y<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>parent_label,                  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># how to label it</span></span>
<span id="cb15-6">    item_tfms<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[Resize(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">192</span>, ...)]         <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># how to transform it</span></span>
<span id="cb15-7">)</span></code></pre></div></div>
<p>Think of it like a crate with items inside. The crate has a sticker informing us how to handle the items within.</p>
<p>Think of <code>.dataloaders</code> like the dude unpacking the crate.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb16" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1">DataBlock(</span>
<span id="cb16-2">    ...</span>
<span id="cb16-3">).dataloaders(path, bs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">32</span>)</span></code></pre></div></div>
<p><code>bs</code>, short for batch size, tells the dude how many items to unpack from the crate and put at the shelf at any given moment.</p>
<p>More technically, <code>DataLoaders</code> turns this block into actual iterators that feed batches of data to your model during training.</p>
<p><strong>Pre-trained models</strong></p>
<p>You may have noticed that our <code>vision_learner</code> was passed <code>resnet18</code>. This is an already existing model, already trained on ImageNet—1 million images across 1000 categories. It already knows edges, textures, shapes, even some animals.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb17" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb17-1">learn <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> vision_learner(dls, resnet18, metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>error_rate)</span></code></pre></div></div>
<p>When you create a learner, fastai downloads those pre-trained weights automatically.</p>
<p><strong>Fine-tuning</strong></p>
<p>You’re not training from scratch. You’re adjusting an expert:</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb18" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1">learn.fine_tune(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span></code></pre></div></div>
<p>Models have something called weights. They guide the model to the correct answer. For our case, that’s bird or forest. In three loops, the model tweaks the weights so it getes better at determining what’s a bird and what’s a forest.</p>
<p>The model already knows “bird-like features.” You’re just teaching it: “these specific birds, not those specific forests.”</p>
<p>That’s why it can take 30 seconds instead of 30 hours.</p>
<p><strong>Predictions</strong></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb19" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb19-1">is_bird, _, probs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> learn.predict(PILImage.create(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bird.jpg'</span>))</span></code></pre></div></div>
<p>Returns three things: the predicted label, the label index, and probabilities for each category.</p>
<p><strong>The process, start to finish:</strong></p>
<ol type="1">
<li><strong>Collect data</strong> – Download images, organize into folders by category</li>
<li><strong>Process Data</strong> – Tell fastai: input type, output type, how to find files, how to split, how to label</li>
<li><strong>Load Data</strong> – Package the data into batches the model can consume</li>
<li><strong>Create learner</strong> – Combine your data with a pre-trained model (like resnet18)</li>
<li><strong>Fine-tune</strong> – Adjust the pre-trained weights to your specific task</li>
<li><strong>Predict</strong> – Use the trained model on new images</li>
</ol>
<p>This pattern works for almost any image classification problem. Different images, same steps.</p>
</section>
<section id="beyond-birds" class="level2">
<h2 class="anchored" data-anchor-id="beyond-birds">Beyond Birds</h2>
<p>The same six-step pattern works for completely different problems.</p>
<p><strong>Segmentation</strong> – Label every pixel in an image by what it represents. Point at a road scene and the model colors cars brown, roads gray, buildings red, sky blue. Same process: organize pixel-labeled images, create DataLoaders, use a segmentation learner, fine-tune.</p>
<p><strong>Tabular data</strong> – Predict outcomes from spreadsheets. Will this customer churn? What salary range fits these demographics? Organize your CSV, tell fastai which columns are categories vs numbers, create a tabular learner, fit. No pre-trained models here—every table is unique.</p>
<p><strong>Collaborative filtering</strong> – Recommend products based on what similar users liked. “Users who rated movie X highly also liked movie Y.” Organize user-item-rating data, create collaborative filtering DataLoaders, fine-tune. This powers Netflix, Spotify, Amazon.</p>
<p><strong>Text classification</strong> – Detect sentiment, filter spam, categorize documents. Organize labeled text, create text DataLoaders, use a text classifier (pre-trained on Wikipedia), fine-tune to your specific task.</p>
<p>Different domains, same structure. The pattern is portable.</p>
<p>For detailed examples, see the <a href="https://docs.fast.ai/">fastai docs</a>.</p>
</section>
<section id="your-turn" class="level2">
<h2 class="anchored" data-anchor-id="your-turn">Your Turn</h2>
<p>You now know enough to build your own classifier. Pick something you care about:</p>
<ul>
<li>Healthy vs diseased plants</li>
<li>Your handwriting vs someone else’s</li>
<li>Cats vs dogs (classic, but effective)</li>
<li>Different types of clouds</li>
<li>Your face vs not your face</li>
</ul>
<p>The steps are the same:</p>
<ol type="1">
<li>Search and download 50-200 images per category</li>
<li>Create a DataBlock</li>
<li>Make DataLoaders and check with <code>show_batch()</code></li>
<li>Create a vision learner with resnet18</li>
<li>Fine-tune for 3-5 epochs</li>
<li>Test predictions</li>
</ol>
<p>Start simple. Two categories. Small dataset. Get something working in the next hour.</p>
<p><strong>What to do next:</strong></p>
<ul>
<li>Read <a href="https://github.com/fastai/fastbook">Chapter 1 of the fastai book</a> - same material, different angle</li>
<li>Try the <a href="https://course.fast.ai/">official fastai course</a> for video walkthroughs</li>
<li>Share your project on the <a href="https://forums.fast.ai/">fastai forums</a> - the community is helpful and encouraging</li>
</ul>
<p>Don’t wait until you understand everything. Build first, understand later. That’s how you actually learn.</p>
<hr>
<p>If you have any comments, questions, suggestions, feedback, criticisms, or corrections, please do post them down in the comment section below!</p>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Creating Models</category>
  <category>fastai</category>
  <guid>https://forbo7.github.io/forblog/posts/29_lets_build_an_ai_model.html</guid>
  <pubDate>Thu, 27 Nov 2025 00:00:00 GMT</pubDate>
  <media:content url="https://forbo7.github.io/forblog/images/29_lets_build_an_ai_model/thumbnail.png" medium="image" type="image/png" height="81" width="144"/>
</item>
<item>
  <title>Creating Your Own LLM Agent</title>
  <dc:creator>Salman Naqvi</dc:creator>
  <link>https://forbo7.github.io/forblog/posts/28_creating_your_own_llm_agent.html</link>
  <description><![CDATA[ 




<p><img src="https://forbo7.github.io/forblog/images/28_creating_your_own_llm_agent/thumbnail.png" class="img-fluid"></p>
<p>In this notebook, I’ll be demonstrating how simple LLM “agents” are, that they’re just LLMs in a while loop calling functions, and how to implement a tool-loop yourself using the <a href="https://lisette.answer.ai/">Lisette</a> and <a href="https://answerdotai.github.io/toolslm/">toolslm</a> libraries.</p>
<div class="callout callout-style-simple callout-note">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>This post is based on the contents of Lesson 2 of the <a href="solve.it.com">SolveIt</a> course led by <a href="https://solve.it.com/#im-jeremy-howard-from-fastai">Jeremy Howard</a> who created the first modern LLM in 2016, and <a href="https://www.johnowhitaker.com/">Johnothan Whitaker</a>. SolveIt is also a brilliant problem-solving framework and interactive platform, that puts you in control–not the LLM.</p>
<p>In lesson 2, Jeremy unmasks the deceptively complicated mask that LLM agents wear iteratively through SolveIt, revealing that agents are just LLMs in a while-loop.</p>
</div>
</div>
</div>
<section id="what-are-agents" class="level2">
<h2 class="anchored" data-anchor-id="what-are-agents">What are Agents?</h2>
<p><strong>“An AI agent is just an LLM in a while loop.”</strong></p>
<p>That’s it. The LLM requests to run a function (or in other words, the tool), you run it, give back the result, and repeat until the LLM no longer requests. No fancy frameworks needed.</p>
<section id="the-core-loop" class="level3">
<h3 class="anchored" data-anchor-id="the-core-loop">The Core Loop</h3>
<p>At its core, it’s simple 4 step loop:</p>
<ol type="1">
<li>Send message + available tools to the LLM</li>
<li>LLM responds with either the answer OR tool request</li>
<li>If tool is requested: execute the relevant function and add the result to the chat history</li>
<li>Go back to step 1.</li>
</ol>
<div class="cell" data-layout-align="default">
<div class="cell-output-display">
<div>
<p></p><figure class="figure"><p></p>
<div>
<pre class="mermaid mermaid-js">flowchart TD
    Start([Start]) --&gt; Call[Call LLM with message + tools]
    Call --&gt; Check{Tool requested?}
    Check --&gt;|Yes| Execute[Execute tool function]
    Execute --&gt; Add[Add result to history]
    Add --&gt; Call
    Check --&gt;|No| Done([Done])
</pre>
</div>
<p></p></figure><p></p>
</div>
</div>
</div>
</section>
<section id="walkthrough" class="level3">
<h3 class="anchored" data-anchor-id="walkthrough">Walkthrough</h3>
<section id="step-1-send-message-and-available-tools-to-llm" class="level4">
<h4 class="anchored" data-anchor-id="step-1-send-message-and-available-tools-to-llm">Step 1: Send Message and Available Tools to LLM</h4>
<p>To do this, we first need to setup the tools by:</p>
<ul>
<li>Tossing all the tools into a list</li>
<li>Defining the metadata about those tools</li>
<li>Making the tools available in a “namespace” through which they can directly be called.</li>
</ul>
<p>Let’s first define two tools.</p>
<div id="c9bc1e05" class="cell" data-time_run="2025-11-24T00:25:20.265772+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> multer(a:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>,b:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>:</span>
<span id="cb1-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">'Take the product of two numbers'</span></span>
<span id="cb1-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> a<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>b</span>
<span id="cb1-4">multer(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre data-code-line-numbers=""><code>6</code></pre>
</div>
</div>
<div id="877916b9" class="cell" data-time_run="2025-11-24T00:25:20.355435+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">pow</span>(a:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>,b:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-&gt;</span><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>:</span>
<span id="cb3-2">    <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">'Return a to the power of b'</span></span>
<span id="cb3-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> a<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>b</span>
<span id="cb3-4"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">pow</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre data-code-line-numbers=""><code>8</code></pre>
</div>
</div>
<p>And then add it to the list of available tools.</p>
<div id="e20a4af5" class="cell" data-time_run="2025-11-24T00:25:20.454907+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1">tools <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [multer,<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">pow</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> tools</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre data-code-line-numbers=""><code>[&lt;function __main__.multer(a: float, b: float) -&gt; float&gt;,
 &lt;function __main__.pow(a: float, b: float) -&gt; float&gt;]</code></pre>
</div>
</div>
<p>We’ll now create the metadata about this tool.</p>
<div id="d3e755ad" class="cell" data-time_run="2025-11-24T00:25:23.352646+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> lisette <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span></span></code></pre></div></div>
</div>
<p><a href="https://lisette.answer.ai/">Lisette</a> is a wonderful library that abstracts away a lot of the boilerplate when working the LLMs in Python. The library is a wrapper around LiteLLM.</p>
<p>Later in the notebook, I’ll demonstrate how to use Lisette’s <code>Chat</code> class directly to make tool calls with an LLM. For now, I’m using some of the library’s other functions.</p>
<div id="f2e144a2" class="cell" data-time_run="2025-11-24T00:25:23.435856+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1">schemas <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [lite_mk_func(t) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> t <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> tools]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> schemas</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre data-code-line-numbers=""><code>[{'type': 'function',
  'function': {'name': 'multer',
   'description': 'Take the product of two numbers\n\nReturns:\n- type: number',
   'parameters': {'type': 'object',
    'properties': {'a': {'type': 'number', 'description': ''},
     'b': {'type': 'number', 'description': ''}},
    'required': ['a', 'b']}}},
 {'type': 'function',
  'function': {'name': 'pow',
   'description': 'Return a to the power of b\n\nReturns:\n- type: number',
   'parameters': {'type': 'object',
    'properties': {'a': {'type': 'number', 'description': ''},
     'b': {'type': 'number', 'description': ''}},
    'required': ['a', 'b']}}}]</code></pre>
</div>
</div>
<div id="b824e782" class="cell" data-time_run="2025-11-24T00:25:23.538485+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1">??lite_mk_func</span></code></pre></div></div>
<div class="cell-output cell-output-display cell-output-markdown">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb11" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> lite_mk_func(f):</span>
<span id="cb11-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">isinstance</span>(f, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> f</span>
<span id="cb11-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'type'</span>:<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'function'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'function'</span>:get_schema(f, pname<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'parameters'</span>)}</span></code></pre></div></div>
<p><strong>File:</strong> <code>/usr/local/lib/python3.12/site-packages/lisette/core.py</code></p>
</div>
</div>
<p>I’ll now define the namespace.</p>
<div id="e811638b" class="cell" data-time_run="2025-11-24T00:25:23.582397+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> toolslm.funccall <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> mk_ns</span></code></pre></div></div>
</div>
<p><a href="https://answerdotai.github.io/toolslm/">toolslm</a> is a helper library used by Lisette.</p>
<div id="88b8938d" class="cell" data-time_run="2025-11-24T00:25:23.628505+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1">ns <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> mk_ns(tools)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> ns</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre data-code-line-numbers=""><code>{'multer': &lt;function __main__.multer(a: float, b: float) -&gt; float&gt;,
 'pow': &lt;function __main__.pow(a: float, b: float) -&gt; float&gt;}</code></pre>
</div>
</div>
<div id="311d299b" class="cell" data-time_run="2025-11-24T00:25:23.670956+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb15" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb15-1">??mk_ns</span></code></pre></div></div>
<div class="cell-output cell-output-display cell-output-markdown">
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb16" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> mk_ns(fs):</span>
<span id="cb16-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">isinstance</span>(fs, abc.Mapping): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> fs</span>
<span id="cb16-3">    merged <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span>
<span id="cb16-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> o <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> listify(fs):</span>
<span id="cb16-5">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">isinstance</span>(o, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>): merged <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|=</span> o</span>
<span id="cb16-6">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">elif</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">callable</span>(o) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">and</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">hasattr</span>(o, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'__name__'</span>): merged <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">|=</span> {o.<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">__name__</span>: o}</span>
<span id="cb16-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> merged</span></code></pre></div></div>
<p><strong>File:</strong> <code>/usr/local/lib/python3.12/site-packages/toolslm/funccall.py</code></p>
</div>
</div>
</section>
<section id="step-2-make-the-first-api-call" class="level4">
<h4 class="anchored" data-anchor-id="step-2-make-the-first-api-call">Step 2: Make the First API Call</h4>
<p>We’ll now send a message to the LLM endpoint asking it to complete a somewhat complex calculation.</p>
<div id="d452cd28" class="cell" data-time_run="2025-11-24T00:25:23.720247+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb17" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb17-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fastcore.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">all</span> <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span></span>
<span id="cb17-2">os.environ[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'MOONSHOT_API_BASE'</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'https://api.moonshot.cn/v1'</span></span></code></pre></div></div>
</div>
<p>Here I’ve just changed my API end-point from <code>'https://api.moonshot.ai/v1'</code> to <code>'https://api.moonshot.cn/v1'</code> as my API key is only compatible with servers based in China.</p>
<div id="37e14439" class="cell" data-time_run="2025-11-24T00:25:30.810956+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb18" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb18-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> litellm <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> completion</span>
<span id="cb18-2">hist <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'role'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'user'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'content'</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Calculate 2*2353**5*1/2'</span>}]</span>
<span id="cb18-3">r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> completion(model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'moonshot/kimi-k2-0711-preview'</span>, messages<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>hist, tools<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>schemas)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> r</span></code></pre></div></div>
<div class="cell-output cell-output-display cell-output-markdown" data-execution_count="1">
<p>I need to calculate 2 * 2353^5 * 1/2.</p>
<p>Let me break this down: - First, I’ll calculate 2353^5 - Then multiply by 2 - Then multiply by 1/2 (which is the same as dividing by 2)</p>
<p>Let me start with 2353^5:</p>
<p>🔧 pow({“a”: 2353, “b”: 5})</p>
<details>
<ul>
<li>id: <code>chatcmpl-6923a5f5ce7148a79dfc95ba</code></li>
<li>model: <code>moonshot/kimi-k2-0711-preview</code></li>
<li>finish_reason: <code>tool_calls</code></li>
<li>usage: <code>Usage(completion_tokens=93, prompt_tokens=111, total_tokens=204, completion_tokens_details=None, prompt_tokens_details=None)</code></li>
</ul>
</details>
</div>
</div>
<div id="b7429b59" class="cell" data-time_run="2025-11-24T00:25:30.894256+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb19" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb19-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(r)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>ModelResponse(id='chatcmpl-6923a5f5ce7148a79dfc95ba', created=1763943925, model='moonshot/kimi-k2-0711-preview', object='chat.completion', system_fingerprint=None, choices=[Choices(finish_reason='tool_calls', index=0, message=Message(content="I need to calculate 2 * 2353^5 * 1/2.\n\nLet me break this down:\n- First, I'll calculate 2353^5\n- Then multiply by 2\n- Then multiply by 1/2 (which is the same as dividing by 2)\n\nLet me start with 2353^5:", role='assistant', tool_calls=[ChatCompletionMessageToolCall(index=0, function=Function(arguments='{"a": 2353, "b": 5}', name='pow'), id='pow:0', type='function')], function_call=None, provider_specific_fields={'refusal': None}), provider_specific_fields={})], usage=Usage(completion_tokens=93, prompt_tokens=111, total_tokens=204, completion_tokens_details=None, prompt_tokens_details=None), service_tier=None)</code></pre>
</div>
</div>
</section>
<section id="step-3-check-if-a-tool-call-was-requested" class="level4">
<h4 class="anchored" data-anchor-id="step-3-check-if-a-tool-call-was-requested">Step 3: Check if a Tool Call was Requested</h4>
<p>We can see that a tool call was requested.</p>
<div id="757530b1" class="cell" data-time_run="2025-11-24T00:25:30.966136+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb21" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb21-1">r.choices[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].finish_reason</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre data-code-line-numbers=""><code>'tool_calls'</code></pre>
</div>
</div>
</section>
<section id="step-4-execute-it" class="level4">
<h4 class="anchored" data-anchor-id="step-4-execute-it">Step 4: Execute It</h4>
<p>All that’s left is, well, to execute it.</p>
<div id="5e4d1893" class="cell" data-time_run="2025-11-24T00:25:31.039256+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb23" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb23-1">tc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> r.choices[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].message.tool_calls[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].to_dict()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> tc</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre data-code-line-numbers=""><code>{'index': 0,
 'function': {'arguments': '{"a": 2353, "b": 5}', 'name': 'pow'},
 'id': 'pow:0',
 'type': 'function'}</code></pre>
</div>
</div>
<div id="7d208b68" class="cell" data-time_run="2025-11-24T00:25:31.105164+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb25" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb25-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> json</span>
<span id="cb25-2">res <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ns[tc[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'function'</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'name'</span>]](<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>json.loads(tc[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'function'</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'arguments'</span>]))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> res</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre data-code-line-numbers=""><code>72128954282026993</code></pre>
</div>
</div>
</section>
<section id="step-5-build-history" class="level4">
<h4 class="anchored" data-anchor-id="step-5-build-history">Step 5: Build History</h4>
<div id="b0123f2f" class="cell" data-time_run="2025-11-24T00:25:31.157276+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb27" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb27-1">hist.append(r.choices[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].message)</span>
<span id="cb27-2">hist.append(mk_tc_result(tc, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>(res)))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> hist</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre data-code-line-numbers=""><code>[{'role': 'user', 'content': 'Calculate 2*2353**5*1/2'},
 Message(content="I need to calculate 2 * 2353^5 * 1/2.\n\nLet me break this down:\n- First, I'll calculate 2353^5\n- Then multiply by 2\n- Then multiply by 1/2 (which is the same as dividing by 2)\n\nLet me start with 2353^5:", role='assistant', tool_calls=[ChatCompletionMessageToolCall(index=0, function=Function(arguments='{"a": 2353, "b": 5}', name='pow'), id='pow:0', type='function')], function_call=None, provider_specific_fields={'refusal': None}),
 {'tool_call_id': 'pow:0',
  'role': 'tool',
  'name': 'pow',
  'content': '72128954282026993'}]</code></pre>
</div>
</div>
</section>
<section id="and-thats-all" class="level4">
<h4 class="anchored" data-anchor-id="and-thats-all">And that’s all!</h4>
<p>Now we just have to keep looping until the query is solved.</p>
<div id="641e9cfc" class="cell" data-time_run="2025-11-24T00:25:35.420250+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb29" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb29-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> r.choices[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].finish_reason<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'stop'</span>:</span>
<span id="cb29-2">    mtcd <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> r.choices[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].message.tool_calls[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].to_dict()</span>
<span id="cb29-3">    o <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ns[mtcd[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'function'</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'name'</span>]](<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>json.loads(mtcd[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'function'</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'arguments'</span>]))</span>
<span id="cb29-4">    tc_res <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> mk_tc_result(mtcd, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>(o))</span>
<span id="cb29-5">    hist.append(r.choices[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].message)</span>
<span id="cb29-6">    hist.append(tc_res)</span>
<span id="cb29-7">    r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> completion(model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'moonshot/kimi-k2-0711-preview'</span>, messages<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>hist, tools<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>schemas)</span></code></pre></div></div>
</div>
<div id="2c8c7e01" class="cell" data-time_run="2025-11-24T00:25:35.491295+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb30" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb30-1">r.choices[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].finish_reason</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre data-code-line-numbers=""><code>'stop'</code></pre>
</div>
</div>
<div id="2df5c4b0" class="cell" data-time_run="2025-11-24T00:25:35.583480+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb32" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb32-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> pprint <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pprint <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pp</span>
<span id="cb32-2">pp(hist)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>[{'content': 'Calculate 2*2353**5*1/2', 'role': 'user'},
 Message(content="I need to calculate 2 * 2353^5 * 1/2.\n\nLet me break this down:\n- First, I'll calculate 2353^5\n- Then multiply by 2\n- Then multiply by 1/2 (which is the same as dividing by 2)\n\nLet me start with 2353^5:", role='assistant', tool_calls=[{'index': 0, 'function': {'arguments': '{"a": 2353, "b": 5}', 'name': 'pow'}, 'id': 'pow:0', 'type': 'function'}], function_call=None, provider_specific_fields={'refusal': None}),
 {'content': '72128954282026993',
  'name': 'pow',
  'role': 'tool',
  'tool_call_id': 'pow:0'},
 Message(content="I need to calculate 2 * 2353^5 * 1/2.\n\nLet me break this down:\n- First, I'll calculate 2353^5\n- Then multiply by 2\n- Then multiply by 1/2 (which is the same as dividing by 2)\n\nLet me start with 2353^5:", role='assistant', tool_calls=[{'index': 0, 'function': {'arguments': '{"a": 2353, "b": 5}', 'name': 'pow'}, 'id': 'pow:0', 'type': 'function'}], function_call=None, provider_specific_fields={'refusal': None}),
 {'content': '72128954282026993',
  'name': 'pow',
  'role': 'tool',
  'tool_call_id': 'pow:0'}]</code></pre>
</div>
</div>
</section>
<section id="refactored" class="level4">
<h4 class="anchored" data-anchor-id="refactored">Refactored</h4>
<div id="6bd09ca3" class="cell" data-time_run="2025-11-24T00:25:35.626918+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb34" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb34-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> set_tools(tools):</span>
<span id="cb34-2">    tools <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> listify(tools)</span>
<span id="cb34-3">    schemas <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [lite_mk_func(t) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> t <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> tools]</span>
<span id="cb34-4">    ns <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> mk_ns(tools)</span>
<span id="cb34-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> tools, schemas, ns</span></code></pre></div></div>
</div>
<div id="8efe9bf9" class="cell" data-time_run="2025-11-24T00:25:35.709152+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb35" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb35-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> make_query(m,h,s):</span>
<span id="cb35-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> completion(model<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>m, messages<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>h, tools<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>s)</span></code></pre></div></div>
</div>
<div id="262a0962" class="cell" data-time_run="2025-11-24T00:25:35.747420+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb36" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb36-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> tc2dict(r):</span>
<span id="cb36-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> r.choices[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].message.tool_calls[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].to_dict()</span></code></pre></div></div>
</div>
<div id="b1212b7e" class="cell" data-time_run="2025-11-24T00:25:35.796245+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb37" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb37-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> run_tool(tc,ns):</span>
<span id="cb37-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> ns[tc[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'function'</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'name'</span>]](<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>json.loads(tc[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'function'</span>][<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'arguments'</span>]))</span></code></pre></div></div>
</div>
<div id="e8d2565a" class="cell" data-time_run="2025-11-24T00:27:40.672431+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb38" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb38-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> build_hist(h,r,tc_res):</span>
<span id="cb38-2">    h.append(r.choices[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].message)</span>
<span id="cb38-3">    h.append(mk_tc_result(r.choices[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].message.tool_calls[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>],<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">str</span>(tc_res)))</span></code></pre></div></div>
</div>
<div id="0b881a40" class="cell" data-time_run="2025-11-24T00:25:35.898853+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb39" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb39-1">hist <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'role'</span>:<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'user'</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'content'</span>:<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Determine 2*3**4**5'</span>}]</span>
<span id="cb39-2">tools, schemas, ns <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> set_tools([multer,<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">pow</span>])</span></code></pre></div></div>
</div>
<div id="55f4cfcf" class="cell" data-time_run="2025-11-24T00:25:40.608935+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb40" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb40-1">r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_query(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'moonshot/kimi-k2-0711-preview'</span>,hist,schemas)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> r</span></code></pre></div></div>
<div class="cell-output cell-output-display cell-output-markdown" data-execution_count="1">
<p>I’ll solve this step by step, following the order of operations for exponentiation (which is right-associative). The expression 2*3<strong>4</strong>5 means 2×(3<sup>(4</sup>5)).</p>
<p>🔧 pow({“a”: 4, “b”: 5})</p>
<details>
<ul>
<li>id: <code>chatcmpl-6923a600bd9f0794473f54b0</code></li>
<li>model: <code>moonshot/kimi-k2-0711-preview</code></li>
<li>finish_reason: <code>tool_calls</code></li>
<li>usage: <code>Usage(completion_tokens=65, prompt_tokens=108, total_tokens=173, completion_tokens_details=None, prompt_tokens_details=None, cached_tokens=108)</code></li>
</ul>
</details>
</div>
</div>
<div id="a18263ea" class="cell" data-time_run="2025-11-24T00:28:09.511287+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb41" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb41-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">while</span> r.choices[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].finish_reason <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'stop'</span>:</span>
<span id="cb41-2">    tc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tc2dict(r)</span>
<span id="cb41-3">    tc_res <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> run_tool(tc, ns)</span>
<span id="cb41-4">    build_hist(hist,r,tc_res)</span>
<span id="cb41-5">    r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> make_query(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'moonshot/kimi-k2-0711-preview'</span>, hist, schemas)</span></code></pre></div></div>
</div>
<div id="34bfce4a" class="cell" data-time_run="2025-11-24T00:29:11.534551+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb42" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb42-1">hist</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre data-code-line-numbers=""><code>[{'role': 'user', 'content': 'Determine 2*3**4**5'},
 Message(content="I'll solve this step by step, following the order of operations for exponentiation (which is right-associative). The expression 2*3**4**5 means 2×(3^(4^5)).", role='assistant', tool_calls=[{'index': 0, 'function': {'arguments': '{"a": 4, "b": 5}', 'name': 'pow'}, 'id': 'pow:0', 'type': 'function'}], function_call=None, provider_specific_fields={'refusal': None}),
 {'tool_call_id': 'pow:0', 'role': 'tool', 'name': 'pow', 'content': '1024'},
 Message(content="Now I'll calculate 3^1024:", role='assistant', tool_calls=[{'index': 0, 'function': {'arguments': '{"a": 3, "b": 1024}', 'name': 'pow'}, 'id': 'pow:1', 'type': 'function'}], function_call=None, provider_specific_fields={'refusal': None}),
 {'tool_call_id': 'pow:1',
  'role': 'tool',
  'name': 'pow',
  'content': '373391848741020043532959754184866588225409776783734007750636931722079040617265251229993688938803977220468765065431475158108727054592160858581351336982809187314191748594262580938807019951956404285571818041046681288797402925517668012340617298396574731619152386723046235125934896058590588284654793540505936202376547807442730582144527058988756251452817793413352141920744623027518729185432862375737063985485319476416926263819972887006907013899256524297198527698749274196276811060702333710356481'},
 Message(content="Finally, I'll multiply this by 2:", role='assistant', tool_calls=[{'index': 0, 'function': {'arguments': '{"a": 2, "b": 373391848741020043532959754184866588225409776783734007750636931722079040617265251229993688938803977220468765065431475158108727054592160858581351336982809187314191748594262580938807019951956404285571818041046681288797402925517668012340617298396574731619152386723046235125934896058590588284654793540505936202376547807442730582144527058988756251452817793413352141920744623027518729185432862375737063985485319476416926263819972887006907013899256524297198527698749274196276811060702333710356481}', 'name': 'multer'}, 'id': 'multer:2', 'type': 'function'}], function_call=None, provider_specific_fields={'refusal': None}),
 {'tool_call_id': 'multer:2',
  'role': 'tool',
  'name': 'multer',
  'content': '746783697482040087065919508369733176450819553567468015501273863444158081234530502459987377877607954440937530130862950316217454109184321717162702673965618374628383497188525161877614039903912808571143636082093362577594805851035336024681234596793149463238304773446092470251869792117181176569309587081011872404753095614885461164289054117977512502905635586826704283841489246055037458370865724751474127970970638952833852527639945774013814027798513048594397055397498548392553622121404667420712962'}]</code></pre>
</div>
</div>
</section>
</section>
</section>
<section id="using-lisette" class="level2">
<h2 class="anchored" data-anchor-id="using-lisette">Using Lisette</h2>
<p>Lisette is pretty concise. In only 2 lines of code, you can have a tool-loop up and running</p>
<div id="44bd8122" class="cell" data-time_run="2025-11-24T00:31:36.983238+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb44" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb44-1">m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'moonshot/kimi-k2-0711-preview'</span></span>
<span id="cb44-2">c <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Chat(m)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> c</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre data-code-line-numbers=""><code>&lt;lisette.core.Chat at 0x7f45865da300&gt;</code></pre>
</div>
</div>
<div id="4dd6f809" class="cell" data-time_run="2025-11-24T00:31:48.167077+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb46" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb46-1">r <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> c(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Who are you?'</span>)</span></code></pre></div></div>
</div>
<div id="e7a2a8de" class="cell" data-time_run="2025-11-24T00:35:50.413499+00:00">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb47" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb47-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> IPython.display <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> display</span>
<span id="cb47-2">c <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Chat(m, tools<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[multer,<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">pow</span>])</span>
<span id="cb47-3">o <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> c(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"What's the result of (13**2)*25.5?"</span>, max_steps<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>, return_all<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> display(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>o)</span></code></pre></div></div>
<div class="cell-output cell-output-display cell-output-markdown">
<p>I’ll calculate this step by step. First, I’ll compute 13 squared (13**2), and then multiply the result by 25.5.</p>
<p>🔧 pow({“a”: 13, “b”: 2})</p>
<details>
<ul>
<li>id: <code>chatcmpl-6923a854bd9f0794473f563c</code></li>
<li>model: <code>moonshot/kimi-k2-0711-preview</code></li>
<li>finish_reason: <code>tool_calls</code></li>
<li>usage: <code>Usage(completion_tokens=51, prompt_tokens=112, total_tokens=163, completion_tokens_details=None, prompt_tokens_details=None, cached_tokens=112)</code></li>
</ul>
</details>
</div>
<div class="cell-output cell-output-display">
<pre data-code-line-numbers=""><code>{'tool_call_id': 'pow:0', 'role': 'tool', 'name': 'pow', 'content': '169'}</code></pre>
</div>
<div class="cell-output cell-output-display cell-output-markdown">
<p>Now I’ll multiply 169 by 25.5:</p>
<p>🔧 multer({“a”: 169, “b”: 25.5})</p>
<details>
<ul>
<li>id: <code>chatcmpl-6923a861655ccdf1f78a3fd1</code></li>
<li>model: <code>moonshot/kimi-k2-0711-preview</code></li>
<li>finish_reason: <code>tool_calls</code></li>
<li>usage: <code>Usage(completion_tokens=35, prompt_tokens=180, total_tokens=215, completion_tokens_details=None, prompt_tokens_details=None)</code></li>
</ul>
</details>
</div>
<div class="cell-output cell-output-display">
<pre data-code-line-numbers=""><code>{'tool_call_id': 'multer:1',
 'role': 'tool',
 'name': 'multer',
 'content': '4309.5'}</code></pre>
</div>
<div class="cell-output cell-output-display cell-output-markdown">
<p>The result of (13²)×25.5 is <strong>4309.5</strong>.</p>
<details>
<ul>
<li>id: <code>chatcmpl-6923a864ce7148a79dfc97f4</code></li>
<li>model: <code>moonshot/kimi-k2-0711-preview</code></li>
<li>finish_reason: <code>stop</code></li>
<li>usage: <code>Usage(completion_tokens=18, prompt_tokens=236, total_tokens=254, completion_tokens_details=None, prompt_tokens_details=None)</code></li>
</ul>
</details>
</div>
</div>
<p>The only thing to note here is the <code>max_steps</code> parameter. That determines the length of the tool-loop.</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>Building a LLM agent is simpler than it looks seem—at its core, it’s just a LLM calling functions in a loop.</p>
<p>By repeatedly calling the model, executing requested tools, and feeding results back into the conversation history, you create a system that can solve complex multi-step problems.</p>
<p>If you have any comments, questions, suggestions, feedback, criticisms, or corrections, please do post them down in the comment section below!</p>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>LLMs</category>
  <category>Agents</category>
  <category>SolveIt</category>
  <guid>https://forbo7.github.io/forblog/posts/28_creating_your_own_llm_agent.html</guid>
  <pubDate>Mon, 24 Nov 2025 00:00:00 GMT</pubDate>
  <media:content url="https://forbo7.github.io/forblog/images/28_creating_your_own_llm_agent/thumbnail.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>Pulling Back the Curtain on VLM Attention</title>
  <dc:creator>Salman Naqvi</dc:creator>
  <link>https://forbo7.github.io/forblog/posts/27_pulling_back_the_curtain_on_vlm_attention.html</link>
  <description><![CDATA[ 




<section id="foreword" class="level2">
<h2 class="anchored" data-anchor-id="foreword">Foreword</h2>
<p>In this converation, I attempted to understand how <a href="https://github.com/zjysteven/VLM-Visualizer/blob/main/llava_example.ipynb">this</a> notebook, by user <a href="https://github.com/zjysteven">zjysteven</a> visualized the attention placed on an image by a VLM. My main confusion stemmed around the two different attentions that are calculated in the notebook.</p>
</section>
<section id="the-confusion-of-two-attentions" class="level2">
<h2 class="anchored" data-anchor-id="the-confusion-of-two-attentions">The Confusion of Two Attentions</h2>
<p>We observed the code first calculating an <code>llm_attn_matrix</code>. At the time, we thought: <em>“Great, this must cover all attention, including both text and images.”</em> But then, the code computed a separate <code>vis_attn_matrix</code>.</p>
<p><em>“Why recalculate visual attention?”</em> you asked. <em>“Didn’t we already calculate attention for all tokens, including the image tokens?”</em> This was a brilliant question—and the key to understanding the entire process. We gradually realized these two attention types originate from different parts of the model and address fundamentally distinct questions.</p>
</section>
<section id="the-language-model-the-clever-manager" class="level2">
<h2 class="anchored" data-anchor-id="the-language-model-the-clever-manager">The Language Model, the Clever “Manager”</h2>
<p>We first grasped the role of the language model’s (LLM) attention. It acts like a strategic manager. When the model generates a word like “cat,” this “manager” examines the question and image, then decides: <em>“To output ‘cat,’ the image token representing ‘ears’ is most critical, while ‘whiskers’ is moderately important.”</em> Thus, the LLM’s attention answers the <strong>“which”</strong> question. It assigns an importance score to each image token. But here was the catch: these scores are “coarse.” They reveal which large patch matters but not <em>what within the patch</em> the model focuses on. Plotting this alone would color entire patches uniformly, yielding unusable visualizations.</p>
</section>
<section id="the-vision-encoder-the-diligent-analyst" class="level2">
<h2 class="anchored" data-anchor-id="the-vision-encoder-the-diligent-analyst">The Vision Encoder, the Diligent “Analyst”</h2>
<p>So what does the vision encoder’s (ViT) attention do? Initially, we mistakenly assumed it also knew the question. But we soon learned it works like a meticulous “analyst” that completes its job <strong>before</strong> the question ever arrives. Its task is to analyze the image in extreme detail, completely independent of the question. It examines every small image patch and generates a “map” for each, revealing how that patch relates to all others. The ViT’s attention thus answers the <strong>“what”</strong> question—outputting detailed maps without scores. <em>“But if it doesn’t know the question,”</em> you asked, <em>“how would it highlight relevant features? It could focus on irrelevant elements.”</em> You were absolutely right. The ViT alone cannot determine what matters for the question; it merely catalogues all interesting structures in the image.</p>
</section>
<section id="the-power-of-collaboration" class="level2">
<h2 class="anchored" data-anchor-id="the-power-of-collaboration">The Power of Collaboration</h2>
<p>Finally, we understood how everything integrates. It’s a two-step process, like manager and analyst collaborating:</p>
<ol type="1">
<li>The diligent analyst (ViT) first prepares a detailed image analysis report—containing a unique attention “map” for every patch.</li>
<li>The clever manager (LLM) reads the question, consults this report, and selects which maps to use (and their weights).</li>
<li>We, as external observers, then combine these selected maps according to the LLM’s weights to produce the final, clear attention heatmap.</li>
</ol>
<p>The resulting visualization isn’t generated by any single component—it emerges from the symbiosis of both systems, harmonized by our interpretation.</p>
</section>
<section id="end-of-narration" class="level2">
<h2 class="anchored" data-anchor-id="end-of-narration">End of Narration</h2>
<p>If you have any comments, questions, suggestions, feedback, criticisms, or corrections, please do post them down in the comment section below!</p>
</section>
<section id="frequently-asked-questions-faq" class="level2">
<h2 class="anchored" data-anchor-id="frequently-asked-questions-faq">Frequently Asked Questions (FAQ)</h2>
<p><strong>Q: Why do we need two attention mechanisms (LLM’s and ViT’s)?</strong> <em>A:</em> Because they answer two distinct but necessary questions. LLM attention is “coarse,” identifying <em>which</em> patch matters for word generation. ViT attention is “fine,” providing spatial “maps” for each patch to reveal internal image structures.</p>
<p><strong>Q: If the vision encoder doesn’t know my question, isn’t its attention potentially irrelevant?</strong> <em>A:</em> Correct. The ViT objectively analyzes the image, cataloguing all salient structures unrelated to the question. The LLM then acts as a filter, selecting only ViT outputs relevant to the question.</p>
<p><strong>Q: Why not use only the LLM’s attention for plotting? Doesn’t it already know what’s important?</strong> <em>A:</em> LLM attention assigns scores to entire patches but lacks spatial resolution. Plotting it alone would color entire patches uniformly, producing low-detail visualizations. ViT maps provide the necessary granularity.</p>
<p><strong>Q: So the vision encoder generates one attention map per image patch? How do we display so many maps?</strong> <em>A:</em> Exactly. For a 576-patch image, the ViT produces 576 maps. The final heatmap is a <em>weighted average</em> of all 576 maps, with weights derived from the LLM’s importance scores for each patch.</p>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Conversation</category>
  <category>Computer Vision</category>
  <category>LLMs</category>
  <category>Transformers</category>
  <guid>https://forbo7.github.io/forblog/posts/27_pulling_back_the_curtain_on_vlm_attention.html</guid>
  <pubDate>Mon, 04 Aug 2025 00:00:00 GMT</pubDate>
</item>
<item>
  <title>Getting General Purpose Robots by Decomposing Problems and Working with Data</title>
  <dc:creator>Salman Naqvi</dc:creator>
  <link>https://forbo7.github.io/forblog/posts/26_getting_general_purpose_robots_by_decomposing_problems_and_working_with_data.html</link>
  <description><![CDATA[ 




<p><img src="https://forbo7.github.io/forblog/images/26_getting_general_purpose_robots_by_decomposing_problems_and_working_with_data/thumbnail.png" class="img-fluid"></p>
<p>I’ve been going through the RoboOS, RoboBrain, and Robobrain 2.0 papers from the <a href="https://www.baai.ac.cn/">Beijing Academy of Artificial Intelligence (BAAI)</a>.</p>
<p>Most robotic solutions I’ve encountered so far leave me feeling like I’m watching yet another Jenga tower of hacks: blocks ducktaped together for the purpose of solving the previous block’s issues. All without fixing the actual fundamental issue that is the VLM.</p>
<div class="quarto-layout-panel" data-layout-ncol="2">
<div class="quarto-layout-row">
<div class="quarto-layout-cell" style="flex-basis: 50.0%;justify-content: center;">
<p><img src="https://forbo7.github.io/forblog/images/26_getting_general_purpose_robots_by_decomposing_problems_and_working_with_data/1.png" class="img-fluid"></p>
</div>
<div class="quarto-layout-cell" style="flex-basis: 50.0%;justify-content: center;">
<p><img src="https://forbo7.github.io/forblog/images/26_getting_general_purpose_robots_by_decomposing_problems_and_working_with_data/2.png" class="img-fluid"></p>
</div>
</div>
<div class="quarto-layout-row">
<div class="quarto-layout-cell" style="flex-basis: 50.0%;justify-content: flex-start;">
<p><em>My view on the current landscape of general purpose robotics.</em></p>
</div>
</div>
</div>
<p>These series of papers do something that feels like cold drink in a desert of hobbling together complicated pipelines and towers: the papers identify issues with VLMs, and then solve those issues by working with the data.</p>
<p>RoboOS is an overarching system for managing embodied robotic systems. RoboBrain is the VLM/MLLM that executes the plans.</p>
<section id="roboos-a-3-piece-kit-instead-of-a-300-piece-puzzle" class="level2">
<h2 class="anchored" data-anchor-id="roboos-a-3-piece-kit-instead-of-a-300-piece-puzzle">RoboOS: A 3-piece kit instead of a 300-piece puzzle</h2>
<p>RoboOS decomposes the generalizability problem of robotics into three clean layers:</p>
<ul>
<li>The Embodied Brain: A cloud-deployed MLLM that thinks globally–planning, replanning, and correcting errors in real time.</li>
<li>The Cerebellum Skill Library: A plug-and-play toolkit that enables various actions, allowing the robot to perform different functions.</li>
<li>Real-Time Shared Memory: Helps maintain spatial memory, temporal memory, and embodiment memory.</li>
</ul>
<table class="caption-top table">
<colgroup>
<col style="width: 44%">
<col style="width: 36%">
<col style="width: 20%">
</colgroup>
<thead>
<tr class="header">
<th>Component</th>
<th>Analogy</th>
<th>Job</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><strong>Embodied Brain</strong> (cloud LLM)</td>
<td>Control Center</td>
<td>high-level planning, error recovery</td>
</tr>
<tr class="even">
<td><strong>Cerebellum Skill Library</strong> (edge containers)</td>
<td>Toolbox</td>
<td>low-latency skills like grasping, SLAM</td>
</tr>
<tr class="odd">
<td><strong>Real-Time Shared Memory</strong></td>
<td>Whiteboard</td>
<td>spatial, temporal, and robot-state cache</td>
</tr>
</tbody>
</table>
<p>There are three manageable chunks that allows for the creation of systems that are general enough for specialized tasks, but not overly general that its bad at everything. It might not allow for novel actions, but it can allow for known actions. And it allows for each of these pieces to be iterated on through their own merits.</p>
<p>In addition, RoboOS allows for multiple different robots to coordinate with each other. What occured in my mind is that that doesn’t have to be individual separate robots; it could be different pieces of the same robot (e.g., the legs and the hands of a robot).</p>
</section>
<section id="robobrain-solve-the-foundations-and-work-with-the-data" class="level2">
<h2 class="anchored" data-anchor-id="robobrain-solve-the-foundations-and-work-with-the-data">RoboBrain: solve the foundations, and work with the data</h2>
<p>Many general purpose robotic solutions try to remedy issues with VLMs with all sorts of pipelines, gadgets, and gizmos. Rather than actually solving the foundational issue that is the VLM itself. Many solutions use VLMs for purposes that they are exactly bad for. VLMs are langauge biased, spatially blind, and temporally naive.</p>
<p>RoboBrain 1.0 tackled:</p>
<ul>
<li>task planning by using QA pairs that decompose long horizon tasks (“make coffee”) into atomic steps (“reach mug → grasp handle → lift → …”)</li>
<li>affordance identification by using 6k images with bounding boxes of “where you’d actually touch the mug” and LoRA-tuning the LLM</li>
<li>trajectory planning by feeding the LLM start / goal 2-D points and asking it to regress waypoints</li>
</ul>
<p>RoboBrain 2.0 doubles down on this philosophy with improvements in three aspects:</p>
<ul>
<li>Spatial understanding with multiview static images, visual grounding, object pointing, and spatial referring examples</li>
<li>Temporal modeling by linking video frames with positional encoding that tracks both the space and time of each frame, multi-robot planning examples, close-loop interaction examples, and ego-view planning</li>
<li>Reasoning chains</li>
</ul>
<p>What was done for both models was construct a dataset that forced the model to learn these skills.</p>
<p>In addition, the RoboBrain papers did a bunch of data curating so as to ensure desired outputs were obtained: truncating examples, increasing throughput of other examples, limiting certain annotations, ensuring diversity of certain examples, mixing data from various stages, and more. In addition, RoboBrain 2.0 is able to output in a wide variety of modalities, making it suitable for a wide range of embodied robotic tasks.</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>The most prominent parts of these papers that stuck out to me is the focus on decomposing problems into much smaller manageable ones, and fixing problems by working with the data.</p>
<ul>
<li>RoboOS: a minimal, composable OS</li>
<li>RoboBrain: a VLM trained for robotics. Not a VLM adapted to robotics.</li>
</ul>
<p>Maybe this is the viable road to allow enough generalizability in robots.</p>
<p>If you have any comments, questions, suggestions, feedback, criticisms, or corrections, please do post them down in the comment section below!</p>
</section>
<section id="links" class="level2">
<h2 class="anchored" data-anchor-id="links">Links</h2>
<ul>
<li><a href="https://www.baai.ac.cn/en/">BAAI (English)</a></li>
<li><a href="https://www.baai.ac.cn/">BAAI (中文)</a></li>
<li><a href="https://github.com/FlagOpen/RoboOS">RoboOS</a></li>
<li><a href="https://huggingface.co/collections/BAAI/robobrain-681e1389c64d06b3e4a45e44">Robobrain</a></li>
<li><a href="https://huggingface.co/collections/BAAI/robobrain20-6841eeb1df55c207a4ea0036">RoboBrain 2.0</a></li>
</ul>
<p>In addition, RoboBrain 2 contains information about their training and inference infrastructure.</p>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Analyzing Models</category>
  <category>Creating Models</category>
  <category>Data</category>
  <category>Papers</category>
  <category>Robotics</category>
  <category>Thoughts</category>
  <guid>https://forbo7.github.io/forblog/posts/26_getting_general_purpose_robots_by_decomposing_problems_and_working_with_data.html</guid>
  <pubDate>Thu, 24 Jul 2025 00:00:00 GMT</pubDate>
  <media:content url="https://forbo7.github.io/forblog/images/26_getting_general_purpose_robots_by_decomposing_problems_and_working_with_data/thumbnail.png" medium="image" type="image/png" height="257" width="144"/>
</item>
<item>
  <title>Current Ideas in Spatial Understanding</title>
  <dc:creator>Salman Naqvi</dc:creator>
  <link>https://forbo7.github.io/forblog/posts/25_current_ideas_in_spatial_understanding.html</link>
  <description><![CDATA[ 




<p><em>This post was updated with a new paper on <strong>Friday, 18 July 2025</strong>.</em> <em>This post was updated with a new paper on <strong>Monday, 21 July 2025</strong>.</em></p>
<p><img src="https://forbo7.github.io/forblog/images/25_current_ideas_in_spatial_understanding/thumbnail.png" class="img-fluid"></p>
<p>I went through a bunch of papers I found relating to enhancing spatial understanding in VLMs to get an idea of what’s going on. Here, I’ve simply extracted the main idea that was explored. I haven’t evaluated the worthiness/effectiveness of the mentioned ideas.</p>
<p>From what I’ve seen, I’ve noticed the following issues with VLMs:</p>
<ul>
<li>The encoders themselves don’t understand space</li>
<li>VLMs are langauge biased</li>
<li>VLMs place attention at the wrong places</li>
<li>The manner of training is important (i.e,. the dataset provided and the way predictions are made)</li>
</ul>
<section id="d-understanding-and-reconstruction" class="level3">
<h3 class="anchored" data-anchor-id="d-understanding-and-reconstruction">3D Understanding and Reconstruction</h3>
<ul>
<li><strong>3D geometric encoding for monocular images</strong>: Use a 3D geometric encoder to produce 3D tokens from monocular images (RGB only images; no depth map). <em><a href="https://arxiv.org/abs/2505.20279">VLM-3R: Vision language models, augmented with instruction aligned 3D reconstruction</a></em><br>
</li>
<li><strong>Evaluating 3D awareness in image models</strong>: Explores whether image models can “see” in 3D. Finds self-supervised models are good at single-view awareness but fail at multiview awareness. <em><a href="https://arxiv.org/abs/2404.08636">Probing the 3D awareness of Visual Foundation Models</a></em><br>
</li>
<li><strong>CLIP-based 3D-text embedding mapping</strong>: Using CLIP, create an embedding that maps text to 3D point clouds. <em><a href="https://arxiv.org/abs/2506.14238">Unified Representation Space for 3D Visual Grounding</a></em><br>
</li>
<li><strong>Dual-encoder system for 2D semantics and 3D structure</strong>: Enhances spatial understanding with a 2D encoder (for visual semantics) and a 3D encoder (for 3D structure), eliminating the need for 3D data like depth maps, and “intelligently” selecting key frames. <em><a href="https://arxiv.org/abs/2505.23747">Spatial-MLLM: Boosting MLLM Capabilities in Visual-based Spatial Intelligence</a></em><br>
</li>
<li><strong>Intermediate perception token generation</strong>: Trains a VLM to output intermediate perception tokens (e.g., depth tokens) to facilitate its reasoning process. <em><a href="https://arxiv.org/abs/2412.03548">Perception tokens and enhance visual reasoning in multimodal language models</a></em><br>
</li>
<li><strong>Enhanced CLIP with intermediate layers and video support</strong>: A stronger CLIP variant that works on video, uses intermediate layers, scales well, aligns for VL and spatial tasks, and includes a dataset. <em><a href="https://arxiv.org/abs/2504.13181">Perception Encoder: The best visual embeddings are not at the output of the network</a></em><br>
</li>
<li><strong>View-aware spatial reasoning for vision-language models</strong>: Enables vision-language models to answer spatial questions about 3D scenes by generating and using imagined views from different perspectives, paired with a world model for view synthesis. <em><a href="https://arxiv.org/pdf/2507.12508">Mental Exploration: Augmenting Vision-Language Models with View Synthesis for Spatial Reasoning</a></em></li>
</ul>
</section>
<section id="spatial-reasoning-enhancements" class="level3">
<h3 class="anchored" data-anchor-id="spatial-reasoning-enhancements">Spatial Reasoning Enhancements</h3>
<ul>
<li><strong>Incorporating horizontal lines and row-wise scanning</strong>: Introduce horizontal lines to input images, and prompt to scan row-by-row to improve spatial performance. <em><a href="https://arxiv.org/abs/2506.22146">Visual Structures Helps Visual Reasoning: Addressing the Binding Problem in VLMs</a></em><br>
</li>
<li><strong>Implicit Perception Loss for policy optimization</strong>: Extends GRPO by introducing “Implicit Perception Loss” to encourage the model to rely more on visual input. <em><a href="https://arxiv.org/abs/2507.06448v1">Perception-Aware Policy Optimization for Multimodal Reasoning</a></em><br>
</li>
<li><strong>Latent visual token-based reasoning</strong>: Enables VLMs to “imagine” scenes using latent visual tokens (without outputting pixels). <em><a href="https://arxiv.org/abs/2506.17218">Machine Mental Imagery: Empower Multimodal Reasoning with Latent Visual Tokens</a></em></li>
</ul>
</section>
<section id="datasets-and-benchmarks-for-spatial-understanding" class="level3">
<h3 class="anchored" data-anchor-id="datasets-and-benchmarks-for-spatial-understanding">Datasets and Benchmarks for Spatial Understanding</h3>
<ul>
<li><strong>Spatial detail-rich QnA dataset finetuning</strong>: Mixes existing VLMs with a custom image QnA dataset containing object details (presence, depth, 3D positions). <em><a href="https://arxiv.org/abs/2401.12168">SpatialVLM: Endowing VLMs with Spatial Reasoning Capabilities</a></em><br>
</li>
<li><strong>Spatial relationship dataset for robotics</strong>: A dataset to help VLMs learn spatial relationships better. <em><a href="https://arxiv.org/abs/2411.16537">RoboSpatial: Teaching Spatial Understanding to 2D and 3D Vision-Language Models for Robotics</a></em><br>
</li>
<li><strong>Simulated dynamic spatial dataset</strong>: A dataset produced from simulations to help VLMs improve understanding of space and movement. <em><a href="https://arxiv.org/abs/2412.07755">SAT: Dynamic Spatial Aptitude Training for Multimodal Language Models</a></em><br>
</li>
<li><strong>Multi-modal spatial perception benchmark</strong>: Tests how well VLMs understand objects in space and their relation to other images. <em><a href="https://arxiv.org/abs/2505.10604">MIRAGE: A Multi-modal Benchmark for Spatial Perception, Reasoning, and Intelligence</a></em><br>
</li>
<li><strong>Multi-image spatial intelligence benchmark</strong>: Evaluates VLM spatial understanding using multiple images of the same scene. <em><a href="https://arxiv.org/abs/2505.23764">MMSI-Bench: A benchmark for multi-image spatial intelligence</a></em><br>
</li>
<li><strong>Spatial intelligence evaluation framework</strong>: A benchmark to test VLM spatial intelligence. <em><a href="https://arxiv.org/abs/2505.05456">SITE: Towards spatial intelligence through evaluation</a></em><br>
</li>
<li><strong>Multi-view understanding evaluation</strong>: A benchmark to assess VLM performance across varied angles of the same scene, finding VLMs struggle with this. <em><a href="https://arxiv.org/abs/2504.15280">Seeing from Another Perspective: Evaluating Mutli-View Understanding in MLLMs</a></em><br>
</li>
<li><strong>Hierarchical spatial weakness evaluation</strong>: A framework to identify VLM weaknesses, finding VLMs struggle with depth perception, view switching (first/third-person), and physical reasoning (e.g., occlusion). <em><a href="https://arxiv.org/abs/2412.12693">SPHERE: Unveiling Spatial Blindspots in VLMs through Hierarchical Evaluation</a></em><br>
</li>
<li><strong>Depth and object annotation dataset for 3D finetuning</strong>: Creates a custom dataset to finetune a VLM on depth images and object annotations. <em><a href="https://arxiv.org/abs/2503.13111">MM-Spatial: Exploring 3D Spatial Understanding in MLLMs</a></em><br>
</li>
<li><strong>Depth map-annotated dataset finetuning</strong>: Finetunes a VLM on a custom dataset of annotated RGB images + depth maps. <em><a href="https://arxiv.org/abs/2406.01584">SpatialRGPT: Grounded Spatial Reasoning in Vision-Language Models</a></em></li>
<li><strong>RGBD QnA dataset finetuning</strong>: Finetunes a VLM on a custom dataset of annotated RGB images + depth maps + QnA. <em><a href="https://arxiv.org/pdf/2406.13642v1">SpatialBot: Precise Spatial Understanding with Vision Language Models</a></em></li>
</ul>
</section>
<section id="attention-mechanisms-and-visual-feature-utilization" class="level3">
<h3 class="anchored" data-anchor-id="attention-mechanisms-and-visual-feature-utilization">Attention Mechanisms and Visual Feature Utilization</h3>
<ul>
<li><strong>Attention logit temperature adjustment</strong>: Guides attention to relevant image parts by increasing the temperature of attention logits in confident answers. <em><a href="https://arxiv.org/abs/2503.01773">Why is Spatial Reasoning Hard for VLMs? An Attention Mechanism Perspective on Focus Areas</a></em><br>
</li>
<li><strong>Improving visual feature utilization</strong>: Highlights that VLM vision encoders outperform the VLM itself, as VLMs fail to effectively use vision encoder outputs, relying instead on language biases. <em><a href="https://arxiv.org/abs/2506.08008">Hidden in plain sight: VLMs overlook their visual representations</a></em><br>
</li>
<li><strong>Teacher-student training with refiner modules</strong>: Refines CLIP’s spatial awareness using a teacher/student model and a refiner module to remove semantic contamination (noise from irrelevant context). <em><a href="https://arxiv.org/abs/2504.02328">Refining CLIP’s spatial awareness: A Visual-centric Perspective</a></em></li>
</ul>
</section>
<section id="multimodal-and-temporal-spatial-reasoning" class="level3">
<h3 class="anchored" data-anchor-id="multimodal-and-temporal-spatial-reasoning">Multimodal and Temporal Spatial Reasoning</h3>
<ul>
<li><strong>Temporal event prediction and segmentation</strong>: Teaches a model to infer missing parts in video events via cause and effect, and to split videos into non-overlapping events with detailed timestamps. <em><a href="https://arxiv.org/abs/2505.01583">Tempura: Temporal event masked prediction and understanding for reasoning in action</a></em><br>
</li>
<li><strong>Multiframe depth and correspondence learning</strong>: Improves VLMs’ understanding of spatial relationships between frames by teaching depth perception, visual correspondence, and dynamic perception. <em><a href="https://arxiv.org/abs/2505.17015">Multi-SpatialMLLM: Multiframe Spatial Understanding with MLLMs</a></em><br>
</li>
<li><strong>Human motion and video finetuning</strong>: Finetunes a VLM on videos of human actions + skeleton sequences or 3D human movement models, enabling it to output text describing motions. <em><a href="https://arxiv.org/abs/2405.20340">MotionLLM: Understanding Human Behaviors from Human Motions and Videos</a></em></li>
</ul>
</section>
<section id="novel-prompting-and-interaction-methods" class="level3">
<h3 class="anchored" data-anchor-id="novel-prompting-and-interaction-methods">Novel Prompting and Interaction Methods</h3>
<ul>
<li><strong>Iterative visual prompting (“hot and cold”)</strong>: Elicits actionable knowledge from VLMs by having them iteratively select from the best visual suggestions (e.g., arrows/markers on images) instead of outputting actions directly. <em><a href="https://arxiv.org/abs/2402.07872">PIVOT: Iterative Visual Prompting Elicits Actionable Knowledge for VLMs</a></em><br>
</li>
<li><strong>VLM cropping (scanning-like behavior)</strong>: A technique reminiscent of CNN scanning. <em><a href="https://x.com/gabriberton/status/1920362156127555673">VLM Cropping</a></em></li>
</ul>
</section>
<section id="cognitive-and-mental-models-of-space" class="level3">
<h3 class="anchored" data-anchor-id="cognitive-and-mental-models-of-space">Cognitive and Mental Models of Space</h3>
<ul>
<li><strong>Cognitive map exploration</strong>: Explores “cognitive maps” as a way for VLMs to visualize and encode space, studying how they see, remember, and recall spaces. <em><a href="https://arxiv.org/abs/2412.14171">Thinking in Space: How MLLMs See, Remember, and Recall Spaces</a></em><br>
</li>
<li><strong>Latent visual token-based imagination</strong>: Enables VLMs to “imagine” scenes using latent visual tokens (without outputting pixels). <em><a href="https://arxiv.org/abs/2506.17218">Machine Mental Imagery: Empower Multimodal Reasoning with Latent Visual Tokens</a></em></li>
</ul>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>If you have any comments, questions, suggestions, feedback, criticisms, or corrections, please do post them down in the comment section below!</p>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Computer Vision</category>
  <category>LLMs</category>
  <category>Papers</category>
  <category>Robotics</category>
  <guid>https://forbo7.github.io/forblog/posts/25_current_ideas_in_spatial_understanding.html</guid>
  <pubDate>Mon, 14 Jul 2025 00:00:00 GMT</pubDate>
  <media:content url="https://forbo7.github.io/forblog/images/25_current_ideas_in_spatial_understanding/thumbnail.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>The State of Pose Estimation</title>
  <dc:creator>Salman Naqvi</dc:creator>
  <link>https://forbo7.github.io/forblog/posts/24_the_state_of_pose_estimation.html</link>
  <description><![CDATA[ 




<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/thumbnail.png" class="img-fluid"></p>
<section id="foreword" class="level2">
<h2 class="anchored" data-anchor-id="foreword">Foreword</h2>
<p>In this post, I have annotated a presentation I gave at my univesity’s multimodal intelligence lab. I’m a newcomer to general purpose robotics, so I had a different mindset and perspective going in.</p>
<p>At the end of this post, I provide another perspective that arose as I wrote these annotations.</p>
</section>
<section id="annotated-presentation" class="level2">
<h2 class="anchored" data-anchor-id="annotated-presentation">Annotated Presentation</h2>
<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/3.png" class="img-fluid"></p>
<p>Here, I introduce the task assigned to me, which focused on addressing the limitations of VLMs in understanding object poses through fine-tuning on annotated videos.</p>
<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/4.png" class="img-fluid"></p>
<p>The core problem is that current vision-language models (VLMs) struggle with understanding object poses. When queried about an object’s orientation or directional changes, VLMs often fail when even simple complexity is introduced or they forget the object’s prior states.</p>
<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/5.png" class="img-fluid"></p>
<p>The goal is to fine-tune a VLM on videos annotated with pose information to improve its performance in understanding and reasoning about object poses.</p>
<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/7.png" class="img-fluid"></p>
<p>Two main obstacles exist: data and pose models.</p>
<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/8.png" class="img-fluid"></p>
<p>A major obstacle is the lack of existing annotated video datasets with object pose information. Self-recorded samples suffer from limited diversity and aren’t suitable for achieving generalizability. While off-the-shelf video datasets exist, they can’t be easily processed due to pose model requirements.</p>
<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/9.png" class="img-fluid"></p>
<p>Pose estimation models present significant friction due to their specialized input requirements (camera data, reference images, 3D models) and fragmented ecosystem. There’s no standardized text-to-pose interface, requiring manual masking and setup of different libraries/environments for each model.</p>
<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/10.png" class="img-fluid"></p>
<p>The current workflow involves too much friction and insufficient iteration, leading to a lack of confidence in the self-created dataset approach.</p>
<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/11.png" class="img-fluid"></p>
<p>Quick iteration is key. Quick iteration is key. Quick iteration is key.</p>
<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/12.png" class="img-fluid"></p>
<p>The workflow involves multiple steps with numerous variables: recording videos (sample count, duration, frames, pose complexity, object count), segmenting videos into frames, pose annotation (RGB, depth, mask frames, camera metadata), text annotation (QnA pairs), and finally fine-tuning. Each step introduces significant time investment and uncertainty.</p>
<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/13.png" class="img-fluid"></p>
<p>The creation of this dataset is a whole project of its own, with the pose model itself being the core component.</p>
<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/14.png" class="img-fluid"></p>
<p>So I suggested a different direction: why not test the underlying theory but with those pieces of data that have less friction.</p>
<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/15.png" class="img-fluid"></p>
<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/16.png" class="img-fluid"></p>
<p>Given the challenges, a different direction maintaining the same core theory is proposed: testing whether annotating images (with RGBD or other data) improves VLM performance on specific tasks, rather than focusing on pose annotations.</p>
<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/17.png" class="img-fluid"></p>
<p>I also did a few experiments of my own, before I was assigned this project, on RGBD images to test for spatial understanding. An off-the-shelf VLM scored ~28% on a given benchmark, a 100 QnA pair finetune scored ~34%, and a 2000 QnA pair finetune scored ~12%.</p>
<p>My current intuition for the discrepency on the larger sample size is that while there were 2000 samples, there were only 300 unique RGBD images. This is contrary to the 100 QnA pair set which had 100 unique images. The suggests diversity is indeed important, as I pointed out earlier in my presentation.</p>
<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/18.png" class="img-fluid"></p>
<p>Benefits a switching approaches is quicker iteration.</p>
<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/19.png" class="img-fluid"></p>
<p>This new direction enables quicker iteration, allowing me to try more ideas out. I had set up a pipeline in which I was able to conduct those 3 prior benchmarks in a couple of days. With quicker iteration, I was able to already test for diversity. With quicker iteration, I could also test out other ideas, such as: should I keep the RGB and depth images separate? should I overlay the depth image over the RGB image? does using multiple view points of a scene help increase spatial understanding?</p>
<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/20.png" class="img-fluid"></p>
<p>So I am brought to my current perspective on the current state of general purpose robotics: better, more impactful directions exist. Directions that have small steps, but allow for interesting, quick iterations and explorations.</p>
<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/21.jpeg" class="img-fluid"></p>
<p>This is how I currently see the field. I see to many papers and people jumping to fancy pipelines, rather than iterating on the core pieces that underpin those fancy pipelines.</p>
<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/22.png" class="img-fluid"></p>
<p>I’m surprised that the primary reason that these general purpose pipelines use VLMs for suck at the very specific reason. (I know this meme doesn’t match the original intent of the xkcd meme, but it appeared in my mind.)</p>
<p><img src="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/23.png" class="img-fluid"></p>
<p>The field seems to be jumping to complex pipeline integrations rather than conducting small, meaningful iteration experiments. There’s a lack of basic infrastructure for quick experimentation, such as pose estimation models being problematic. Without these basic components and pieces being ironed out, the more interesting directions cannot be explored.</p>
<p>Better directions exist that focus on fundamental improvements through systematic testing rather than complex integrations.</p>
</section>
<section id="closing-words" class="level2">
<h2 class="anchored" data-anchor-id="closing-words">Closing Words</h2>
<p>As I annotated this presention, it just occured to me: overlay pose annotations on videos perhaps might not be needed at all. Current vision models and VLMs can pick out objects in images without the need for, say, a bounding box and label around the object in question. So perhaps, what needs to be done is that, perhaps, QnA pairs are created in a way that allows for the VLM to learn the concept of spaces, depth, poses, etc. The answer describes the manipulation of the object, the change in pose of the object, and so on.</p>
<p>If you have any comments, questions, suggestions, feedback, criticisms, or corrections, please do post them down in the comment section below!</p>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Annotated Presentation</category>
  <category>Approaching AI</category>
  <category>Robotics</category>
  <category>Thoughts</category>
  <guid>https://forbo7.github.io/forblog/posts/24_the_state_of_pose_estimation.html</guid>
  <pubDate>Thu, 10 Jul 2025 00:00:00 GMT</pubDate>
  <media:content url="https://forbo7.github.io/forblog/images/24_the_state_of_pose_estimation/thumbnail.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>中文里的一些基本数学术语</title>
  <dc:creator>Salman Naqvi</dc:creator>
  <link>https://forbo7.github.io/forblog/posts/23_basic_math_terms_in_chinese.html</link>
  <description><![CDATA[ 




<p><img src="https://forbo7.github.io/forblog/images/23_basic_math_terms_in_chinese/thumbnail.png" class="img-fluid"></p>
<section id="算术运算" class="level3">
<h3 class="anchored" data-anchor-id="算术运算">算术运算</h3>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?n%20+%20m"> 是 “n 加 m”.</li>
<li><img src="https://latex.codecogs.com/png.latex?n%20-%20m"> 是 “n 减 m”.</li>
</ul>
</section>
<section id="乘除法" class="level3">
<h3 class="anchored" data-anchor-id="乘除法">乘除法</h3>
<ul>
<li><strong>标准说法：</strong>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?n%20%5Ccdot%20m"> 是 “n 乘以 m”</li>
<li><img src="https://latex.codecogs.com/png.latex?n%20/%20m"> 是 “n 除以 m”</li>
</ul></li>
<li><strong>传统用法：</strong>
<ul>
<li>“n 乘 m” 可能表示 <img src="https://latex.codecogs.com/png.latex?m%20%5Ccdot%20n"></li>
<li>“n 除 m” 可能表示 <img src="https://latex.codecogs.com/png.latex?m%20/%20n"></li>
</ul></li>
</ul>
</section>
<section id="等式相等" class="level3">
<h3 class="anchored" data-anchor-id="等式相等">等式/相等</h3>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?="> 是 “等于”</li>
<li><img src="https://latex.codecogs.com/png.latex?%E2%89%88"> 是 “约等于”</li>
<li><img src="https://latex.codecogs.com/png.latex?%E2%89%A0"> 是 “不等于”</li>
<li><img src="https://latex.codecogs.com/png.latex?%3C"> 是 “小于”</li>
<li><img src="https://latex.codecogs.com/png.latex?%3E"> 是 “大于”</li>
<li><img src="https://latex.codecogs.com/png.latex?%5Cleq"> 是 “小于等于”</li>
<li><img src="https://latex.codecogs.com/png.latex?%5Cgeq"> 是 “小于等于”</li>
</ul>
</section>
<section id="负数" class="level3">
<h3 class="anchored" data-anchor-id="负数">负数</h3>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?-4.87"> 是 “负 4 点 87”</li>
</ul>
</section>
<section id="几何" class="level3">
<h3 class="anchored" data-anchor-id="几何">几何</h3>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?%5Cangle%20ABC"> 是 “角 ABC”</li>
<li><img src="https://latex.codecogs.com/png.latex?%5Ctriangle%20ABC"> 是 “三角形 ABC”</li>
</ul>
</section>
<section id="微积分" class="level3">
<h3 class="anchored" data-anchor-id="微积分">微积分</h3>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?%5Cfrac%7Bdy%7D%7Bdx%7D"> 是 “dy 除以 dx” 或者 “y 对 x 的导数”</li>
<li><img src="https://latex.codecogs.com/png.latex?%5Cint%20f(x)%20dx"> 是 “f(x) 的积分”</li>
</ul>
</section>
<section id="集合论" class="level3">
<h3 class="anchored" data-anchor-id="集合论">集合论</h3>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?%5Cin"> 是 “属于”</li>
<li><img src="https://latex.codecogs.com/png.latex?%5Csubset"> 是 “子集”</li>
</ul>
</section>
<section id="组合数学" class="level3">
<h3 class="anchored" data-anchor-id="组合数学">组合数学</h3>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?C%5E%7Bn%7D_%7Bm%7D"> 是 “n 取 m” 或者 “从 n 个元素中取 m 个元素的组合数”</li>
</ul>
</section>
<section id="阶乘与连乘" class="level3">
<h3 class="anchored" data-anchor-id="阶乘与连乘">阶乘与连乘</h3>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?1%20%5Ccdot%202%20%5Ccdot%203%20%5Ccdot%20%5Ccdots"> 是 “1 乘 2 乘 3 乘 4 一直乘下去”</li>
<li><img src="https://latex.codecogs.com/png.latex?1%20%5Ccdot%202%20%5Ccdot%203%20%5Ccdot%204%20%5Ccdots%20%5Ccdot%20n%20=%20n!"> 是 “1 乘 2 乘 3 一直乘到 n” 或者 “n 的阶乘”</li>
</ul>
</section>
<section id="分数" class="level3">
<h3 class="anchored" data-anchor-id="分数">分数</h3>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?%5Cfrac%7Ba%7D%7Bb%7D"> 是 “b 分之 a”</li>
<li><img src="https://latex.codecogs.com/png.latex?c%5Cfrac%7Ba%7D%7Bb%7D"> 是 “c 又 b 分之 a”</li>
</ul>
</section>
<section id="指数与根式" class="level3">
<h3 class="anchored" data-anchor-id="指数与根式">指数与根式</h3>
<ul>
<li><img src="https://latex.codecogs.com/png.latex?n%5E%7Bm%7D"> 是 “n 次方”</li>
<li><img src="https://latex.codecogs.com/png.latex?%5Csqrt%7Bn%7D"> 是 “根号 n”</li>
<li><img src="https://latex.codecogs.com/png.latex?%5Csqrt%5Bm%5D%7Bn%7D"> 是 “n 的 m 次方根”</li>
</ul>
<hr>
<p>如果你有任何意见、问题、建议、反馈、批评、或更正，请在下方评论区留言！</p>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Mandarin</category>
  <category>Mathematics</category>
  <guid>https://forbo7.github.io/forblog/posts/23_basic_math_terms_in_chinese.html</guid>
  <pubDate>Sun, 08 Jun 2025 00:00:00 GMT</pubDate>
  <media:content url="https://forbo7.github.io/forblog/images/23_basic_math_terms_in_chinese/thumbnail.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>How Deepseek R1 was trained.</title>
  <dc:creator>Salman Naqvi</dc:creator>
  <link>https://forbo7.github.io/forblog/posts/22_how_deepseek_r1_was_trained.html</link>
  <description><![CDATA[ 




<p><img src="https://forbo7.github.io/forblog/images/22_how_deepseek_r1_was_trained/thumbnail.png" class="img-fluid"></p>
<section id="in-a-nutshell" class="level2">
<h2 class="anchored" data-anchor-id="in-a-nutshell">In a Nutshell</h2>
<ul>
<li>R1-Zero is a model created purely through reinforcement learning (RL), with Group Relative Policy Optimization (GRPO) as the policy.</li>
<li>R1 is a model created with a combination of multiple RL and supervised finetuning (SFT) stages.</li>
</ul>
</section>
<section id="r1-zero-the-pure-rl-approach" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="r1-zero-the-pure-rl-approach">R1-Zero: The Pure RL Approach</h2>
<p>R1-Zero was a model developed exclusively through RL using GRPO as the policy. A rule based reward system was utilized with the following two rewards:</p>
<ul>
<li>Accuracy rewards for factual correctness of responses.</li>
<li>Format rewards for pushing the model to put its thinking between <code>&lt;think&gt;</code> and <code>&lt;/think&gt;</code> tags.</li>
</ul>
<p>The neural reward model<sup>1</sup> was left out so as to eliminate reward hacking.</p>
<div class="no-row-height column-margin column-container"><div id="fn1"><p><sup>1</sup>&nbsp;A neural reward model is a neural network trained to predict human preferences or desirability of different actions or states, providing a numerical reward signal that guides RL agents to align with human values. It learns from human feedback, such as comparisons or rankings of different outcomes, to estimate rewards for the RL agent.</p></div></div><p>In addition, a prompt template was used that required the model to first produce the reasoning process, after which, it could produce the answer:</p>
<pre><code>A conversation between User and Assistant. The user asks a question, and the Assistant solves it.
The assistant first thinks about the reasoning process in the mind and then provides the user
with the answer. The reasoning process and answer are enclosed within &lt;think&gt; &lt;/think&gt; and
&lt;answer&gt; &lt;/answer&gt; tags, respectively, i.e., &lt;think&gt; reasoning process here &lt;/think&gt;
&lt;answer&gt; answer here &lt;/answer&gt;. User: prompt. Assistant:</code></pre>
<section id="issues" class="level3">
<h3 class="anchored" data-anchor-id="issues">Issues</h3>
<p>There were certain issues that arose from a pure RL approach:</p>
<ul>
<li>The output was not very readable.</li>
<li>There was language mixing.</li>
</ul>
</section>
</section>
<section id="r1-the-hybrid-training-pipeline" class="level2">
<h2 class="anchored" data-anchor-id="r1-the-hybrid-training-pipeline">R1: The Hybrid Training Pipeline</h2>
<p>In order to remedy these issues, a multi-stage training pipeline was introduced.</p>
<div class="cell" data-layout-align="default">
<div class="cell-output-display">
<div>
<p></p><figure class="figure"><p></p>
<div>
<pre class="mermaid mermaid-js">flowchart LR
  A[SFT]--&gt;B[RL]--&gt;C[SFT]--&gt;D[RL]
  style A fill:#b3e6ff,stroke:#333
  style C fill:#b3e6ff,stroke:#333
  style B fill:#ffb3b3,stroke:#333
  style D fill:#ffb3b3,stroke:#333
</pre>
</div>
<p></p></figure><p></p>
</div>
</div>
</div>
<p>This process arose from wondering whether performance could be improved, convergence accelerated, or a coherent chain-of-thought (CoT) be produced through a small amount of high quality data.</p>
<section id="stage-1-cold-start-sft" class="level3">
<h3 class="anchored" data-anchor-id="stage-1-cold-start-sft">Stage 1: Cold-start SFT</h3>
<p>This stage is performed to prevent the unstable cold start phase of RL. The tuning is done through a small amount of CoT data, which is collected by:</p>
<ul>
<li>Few-shot prompting with a long CoT example.</li>
<li>Direct requests for detailed answers.</li>
<li>Gathering human refined R1-Zero outputs in a readable format.</li>
</ul>
<p>This stage allows for reduced language mixing, improved markdown formatting, and enhanced reader friendly outputs.</p>
<div class="callout callout-style-simple callout-none no-icon">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon no-icon"></i>
</div>
<div class="callout-body-container">
<p>As I was reading this paper, it reminded how I previously read about iterative training processes. Such processes typically result in a better model.</p>
</div>
</div>
</div>
</section>
<section id="stage-2-reasoning-oriented-rl" class="level3">
<h3 class="anchored" data-anchor-id="stage-2-reasoning-oriented-rl">Stage 2: Reasoning-oriented RL</h3>
<p>The goal of this RL stage is on enhancing reasoning capabilities.</p>
<p>A prominent issue found during the training of R1-Zero was language mixing. To alleviate this, a language consistency reward is introduced that is calculated as a proportion of the target language words in the CoT. The introduction of this reward results in a small performance decrease, but results in a significant human readability gain.</p>
<p>The final reward in the RL pipeline was produced by summing the accuracy of the reasoning task with the language consistency reward.</p>
</section>
<section id="stage-3-rejection-sampling-sft" class="level3">
<h3 class="anchored" data-anchor-id="stage-3-rejection-sampling-sft">Stage 3: Rejection Sampling SFT</h3>
<p>SFT is performed once more. In this stage, the checkpoint from the previous round is used to collect data for this stage. Rather than fully focusing on reasoning data like in the first stage, data from other domains is utilized to enhance capabilities in writing, role playing, and other general purpose tasks. In total, an additional 800k samples were collected.</p>
<table class="caption-top table">
<colgroup>
<col style="width: 19%">
<col style="width: 9%">
<col style="width: 35%">
<col style="width: 35%">
</colgroup>
<thead>
<tr class="header">
<th>Data Type</th>
<th>Samples</th>
<th>Source</th>
<th>Filter Criteria</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Reasoning</td>
<td>600k</td>
<td>Curated prompts + sampling</td>
<td>Remove mixed-language/code CoT</td>
</tr>
<tr class="even">
<td>General Purpose</td>
<td>200k</td>
<td>DeepSeek V3 + CoT generation</td>
<td>Simple queries without CoT</td>
</tr>
</tbody>
</table>
</section>
<section id="stage-4-rl-alignment" class="level3">
<h3 class="anchored" data-anchor-id="stage-4-rl-alignment">Stage 4: RL Alignment</h3>
<p>In this stage, RL was performed once more to futher align with human preferences, and to have better reasoning.</p>
<p>To improve helpfulness, the final answer quality was evaluated, with an emphasis on utility and relevance. Focus was placed exclusively on the resulting answer so as to minimize interference with the reasoning process. Harmlessness was improved by analyzing the entire response (including CoT) to identify and mitigate any risks, biases, and harmful content.</p>
<p>The RL pipeline in this stage integrated a multireward models, diverse prompt distributions, and was also based on the DeepSeek V3 pipeline.</p>
</section>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>If you have any comments, questions, suggestions, feedback, criticisms, or corrections, please do post them down in the comment section below!</p>
<p><a href="https://arxiv.org/abs/2501.12948">Read the Deepseek R1 paper here.</a>.</p>


</section>


<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>LLMs</category>
  <category>Papers</category>
  <category>RL</category>
  <guid>https://forbo7.github.io/forblog/posts/22_how_deepseek_r1_was_trained.html</guid>
  <pubDate>Tue, 25 Feb 2025 00:00:00 GMT</pubDate>
  <media:content url="https://forbo7.github.io/forblog/images/22_how_deepseek_r1_was_trained/thumbnail.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>What I Learned during my Second and Third Internships</title>
  <dc:creator>Salman Naqvi</dc:creator>
  <link>https://forbo7.github.io/forblog/posts/21_reflecting_on_my_internships.html</link>
  <description><![CDATA[ 




<p><img src="https://forbo7.github.io/forblog/images/21_reflecting_on_my_internships/thumbnail.jpg" class="img-fluid" alt="a continuously expanding brain; there are lots of swirls swirling around the brain"></p>
<p>I recently completed my second and third internships. These were quite hands on, and involved tasks such as finetuning LLMs to generate Cantonese lyrics to the topic and tones specified. Along the way, I learned <em>a lot</em>. Three months ago, I would not have been able to do what I did. You learn by doing.</p>
<p>Let’s list out some of the things I learned (in no particular order).</p>
<section id="training-strategies" class="level3">
<h3 class="anchored" data-anchor-id="training-strategies">Training Strategies</h3>
<p>I know it sounds really obvious, but one should never start the finetuning process on the full dataset with the largest model variant right out of the box. There will be issues. One may be under the assumption that they’ve implemented the tweaks they needed to on the model, in the first attempt. Or that the data is correctly processed and formatted. However, chances are that they’re not. Save time, money, and resources by finetuning on on a small subset of the data with a smaller model variant. Once it is known the whole process works correctly and as expected, then go ahead with the full finetune.</p>
</section>
<section id="bpe-tokenizers" class="level3">
<h3 class="anchored" data-anchor-id="bpe-tokenizers">BPE Tokenizers</h3>
<p>Byte Pair Encoding (BPE) tokenizers are “dynamic” tokenizers. That is, they do not tokenize text according to a preset vocabulary or set of rules. Rather, they tokenize according to an algorithm. In short, frequent sequences of characters are merged together to form tokens. These tokenizers also store their vocabulary in a data type known as byte strings.</p>
</section>
<section id="gpus" class="level3">
<h3 class="anchored" data-anchor-id="gpus">GPUs</h3>
<p>There are various types of GPUs. I got to try out the mighty A100 all the way to reliable T4. I found the L4 and 4090 to be the sweet spot, though I’d lean towards the latter. Also, if you’re simply going after a GPU, don’t go for the major cloud providers such as Google Cloud. The only reason our company was using Google Cloud was because they had obtained free credits. Otherwise, it’s, well, a rip off when compared to <a href="https://cloud-gpus.com/">other providers</a> (in the context of research).</p>
</section>
<section id="forward-hooks" class="level3">
<h3 class="anchored" data-anchor-id="forward-hooks">Forward Hooks</h3>
<p>A hook is a piece of code that can be inserted at predefined places of an algorithm to achieve extra functionality. In the context of deep learning, a forward hook is a piece of code that is run after the forward pass of a model. By creating a forward hook, one can directly play around with and tweak the computed logits before the loss is calculated.</p>
</section>
<section id="token-generation" class="level3">
<h3 class="anchored" data-anchor-id="token-generation">Token Generation</h3>
<p>With Hugging Face, at least, the way models generate tokens during training and inference is different. During training, all output tokens are generated simultaneously whereas during inference, generation occurs token by token.</p>
<p>However, as I dug behind the scenes of the builtin <code>generate</code> method, I found that during inference, all tokens were actually generated simultaneously–in a way. Say, if 10 tokens were to be generated, for each token, 10 tokens would be generated with the remaining 9 being “filler” tokens.</p>
</section>
<section id="logit-processors" class="level3">
<h3 class="anchored" data-anchor-id="logit-processors">Logit Processors</h3>
<p>Logit processors are nifty objects that Hugging Face provides to be able to conveniently tweak a model’s logits during inference with the builtin <code>generate</code> method.</p>
</section>
<section id="handling-mistakes" class="level3">
<h3 class="anchored" data-anchor-id="handling-mistakes">Handling Mistakes</h3>
<p>Mistakes happen. Especially for challenging tasks. That’s normal. Mistakes should happen. What’s important is that one learns from their mistakes.</p>
</section>
<section id="fsdp" class="level3">
<h3 class="anchored" data-anchor-id="fsdp">FSDP</h3>
<p>Fully Sharded Data Parallel is a technique for splitting a model across multiple GPUs. Imagine literally splitting a model’s parameters into a bunch of different groups, and then putting those groups onto multiple GPUs that run simultaneously. When a layer is being computed on a GPU, all relevant parameters are copied to that GPU.</p>
</section>
<section id="lora" class="level3">
<h3 class="anchored" data-anchor-id="lora">LoRA</h3>
<p>Low Rank Adaptation (LoRA) is a LLM finetuning technique in which new layers are added onto the head of the existing model. These new layers are then trained to achieve a specific task, and form an, well, adapter of sorts. Think of a screwdriver handle onto which you can attach various heads, each head achieving a specific task. In the context of LLMs, these specific tasks could be increasing the performance of a model, reducing its resource usage, or changing what sort of output it generates.</p>
</section>
<section id="quantization" class="level3">
<h3 class="anchored" data-anchor-id="quantization">Quantization</h3>
<p>Quantization is a LLM inference technique whereby the weights in the remaining few layers of the model are stored in 4 or fewer bits, as opposed to the more typical 16 or 32 bits. This allows more weights to be stored in the same amount of memory, and larger models to be fit on smaller hardware, all whilst retaining the relative same level of performance.</p>
</section>
<section id="reading-papers" class="level3">
<h3 class="anchored" data-anchor-id="reading-papers">Reading Papers</h3>
<p>When browsing papers, one typically wants to read the abstract, headings, figures, and results. From this, one can determine whether a given paper is worthy for their goal or not.</p>
<p>When reading a paper, one wants to do it iteratively. In the first iteration, also only read the abstract, figures, and results. In the next iteration, read the paper but not with too much focus. Don’t understand something? That’s fine, move on. In the third iteration, start reading more closely and try to make sense of what is going on. Get bogged down? Spend some more time on it, but not too much more–save it for the next iteration. And so on. As you do more iterations, it may be helpful to rephrase or summarize what each section discusses. This allows you to find gaps in your knowledge and determine whether you understand what you just wrote.</p>
</section>
<section id="looping-and-slicing" class="level3">
<h3 class="anchored" data-anchor-id="looping-and-slicing">Looping and Slicing</h3>
<p>Loops can be immensely slow. I managed to deflate my training time from 10+ hours to around 2 hours by replacing two nested for loops with a single slicing operation.</p>
</section>
<section id="llm-training-data-formats" class="level3">
<h3 class="anchored" data-anchor-id="llm-training-data-formats">LLM Training Data Formats</h3>
<p>There are different ways LLM training data can be formatted. The Alpaca format uses <code>'###'</code> as the delimiter, while ChatML uses the tokens <code>'&lt;|im_start|&gt;</code> and <code>'&lt;|im_end|&gt;'</code> as the delimiters.</p>
</section>
<section id="best-performing-open-source-models" class="level3">
<h3 class="anchored" data-anchor-id="best-performing-open-source-models">Best Performing Open Source Models</h3>
<p>The best performing open source models come from the other side of the Pacific ocean; from China. The AI scene there is quite vibrant, with most of the actual advances happening there. If you look at the latest papers, most of the authors will be from there too. During my internships, I came across so many models I never had heard off that were well performers or had interesting perks or quirks. Qwen is the best performing open source model. Deepseek is the most cost effective endpoint that exists. Then there are so many other models such as InternLM, Yi, PhotoMaker, and more.</p>
</section>
<section id="refactoring" class="level3">
<h3 class="anchored" data-anchor-id="refactoring">Refactoring</h3>
<p>Refactored code is abstracted code. Abstracted code is maintainable code. Abstracted code is understandable code. Abstracted code is good code.</p>
</section>
<section id="data" class="level3">
<h3 class="anchored" data-anchor-id="data">Data</h3>
<p>It’s stating the obvious, but data matters. It actually does influence the quality or manner of the model output.</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>If you have any comments, questions, suggestions, feedback, criticisms, or corrections, please do post them down in the comment section below!</p>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Creating Models</category>
  <category>LLMs</category>
  <category>Papers</category>
  <category>Programming</category>
  <category>Transformers</category>
  <guid>https://forbo7.github.io/forblog/posts/21_reflecting_on_my_internships.html</guid>
  <pubDate>Tue, 24 Sep 2024 00:00:00 GMT</pubDate>
  <media:content url="https://forbo7.github.io/forblog/images/21_reflecting_on_my_internships/thumbnail.jpg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>Implementing a Neural Network from Scratch</title>
  <dc:creator>Salman Naqvi</dc:creator>
  <link>https://forbo7.github.io/forblog/posts/20_models_from_scratch.html</link>
  <description><![CDATA[ 




<blockquote class="blockquote">
<p>This notebook follows the <a href="https://docs.fast.ai/dev/style.html">fastai style guide</a>.</p>
</blockquote>
<p><img src="https://forbo7.github.io/forblog/images/20_model_from_scratch/thumbnail.jpeg" class="img-fluid" alt="The image features a person engaged in wood carving, with their face hidden by a color block. They are wearing an orange robe and using a chisel to create intricate designs on wood. The setting blends elements of a forest and architectural columns, with dramatic lighting that accentuates the carver and their craft. The scene evokes a sense of both indoor and outdoor space, with a focus on the artistry of wood carving."></p>
<div class="callout callout-style-simple callout-note">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>This notebook is based on the contents taught in part 2 of the <a href="https://course.fast.ai/Lessons/part2.html">fastai Course</a>, led by <a href="https://solve.it.com/#im-jeremy-howard-from-fastai">Jeremy Howard</a> who created the first LLM, ULMFiT in 2016.</p>
</div>
</div>
</div>
<p>In this notebook, I will implement a neural network from scratch, and iteratively reimplement with PyTorch. That is, I will implement each element of the training and inference process from scratch, before then using the corresponding element in PyTorch. This notebook assumes a prior understanding of the flow and pieces of a neural network.</p>
<p>To recap, the complete training loop of a neural network looks like this.</p>
<div class="grid">
<div class="g-col-4">

</div>
<div class="g-col-4">
<div class="cell" data-layout-align="default">
<div class="cell-output-display">
<div>
<p></p><figure class="figure"><p></p>
<div>
<pre class="mermaid mermaid-js">graph TB
  A[Load Data] --&gt; B[Make Predictions] --&gt; C[Compute Loss] --&gt; D[Compute Gradients] --&gt; E[Update Weights] --&gt; F[Compute Metric] --&gt; A
</pre>
</div>
<p></p></figure><p></p>
</div>
</div>
</div>
</div>
<div class="g-col-4">

</div>
</div>
<p>This notebook also serves to show the modular nature of PyTorch.</p>
<p>Let’s get started with some data.</p>
<section id="download-data" class="level2">
<h2 class="anchored" data-anchor-id="download-data">Download Data</h2>
<p>The goal of our model will be to classify digits from the MNIST dataset.</p>
<div id="ffcb6dea" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> pathlib <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> Path</span>
<span id="cb1-2">MNIST_URL <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'https://github.com/mnielsen/neural-networks-and-deep-learning/blob/master/data/mnist.pkl.gz?raw=true'</span></span>
<span id="cb1-3">d_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Path(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'data'</span>)</span>
<span id="cb1-4">d_path.mkdir(exist_ok<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb1-5">d_path <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> d_path<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'mnist.pkl.gz'</span></span></code></pre></div></div>
</div>
<div id="e3baf655" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb2" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> urllib.request <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> urlretrieve</span>
<span id="cb2-2"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> d_path.exists(): urlretrieve(MNIST_URL, d_path)</span></code></pre></div></div>
</div>
<div id="4a901219" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span> ls <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>l data</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>total 33312
-rw-r--r--  1 salmannaqvi  staff  17051982 May 12 12:37 mnist.pkl.gz</code></pre>
</div>
</div>
<div id="ba95ef4c" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-4" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-annotation-code code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-4-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> gzip, pickle</span>
<span id="annotated-cell-4-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> torch <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> tensor</span>
<span id="annotated-cell-4-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> gzip.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(d_path, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'rb'</span>) <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> f: ((trn_x, trn_y), (vld_x, vld_y), _) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pickle.load(f, encoding<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'latin-1'</span>)</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-4" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-4-4" class="code-annotation-target">trn_x, trn_y, vld_x, vld_y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(tensor, [trn_x[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>], trn_y[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>], vld_x[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>], vld_y[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span>]])</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-4" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-4" data-code-lines="4" data-code-annotation="1">Taking 1000 samples each for the sake of speed.</span>
</dd>
</dl>
</div>
</div>
</section>
<section id="a-single-neuron" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="a-single-neuron">A Single Neuron</h2>
<p>A neuron comprises of a set of weights, the linear function, and the activation function.</p>
<div class="grid">
<div class="g-col-4">

</div>
<div class="g-col-4">
<div class="cell" data-layout-align="default">
<div class="cell-output-display">
<div>
<p></p><figure class="figure"><p></p>
<div>
<pre class="mermaid mermaid-js">graph LR
  A1[Weights]
  A2[Inputs]
  A1 &amp; A2 --&gt; B[Linear Combination] --&gt; C[Activation Function]
</pre>
</div>
<p></p></figure><p></p>
</div>
</div>
</div>
</div>
<div class="g-col-4">

</div>
</div>
<p>Our dataset contains one thousand 28x28 pixel samples. Therefore, each sample has 28x28=784 inputs. Since we will be classifying digits, there will be 10 outputs–a probablity for each digit.</p>
<div id="afec7458" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1">n, m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_x.shape</span>
<span id="cb5-2">c <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_y.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb5-3">n, m, c</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="5">
<pre data-code-line-numbers=""><code>(1000, 784, tensor(10))</code></pre>
</div>
</div>
<p>Let’s have 50 neurons comprise the hidden layer.</p>
<div id="c6d50249" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1">nh <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span></span></code></pre></div></div>
</div>
<p>From these dimensions, we can create our appropriate weights…</p>
<div id="39d4b494" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> torch<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> torch.set_printoptions(precision<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, linewidth<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">140</span>, sci_mode<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb8-2">w1, b1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.randn(m, nh), torch.zeros(nh)</span>
<span id="cb8-3">w2, b2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.randn(nh, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), torch.zeros(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb8-4">w1.shape, b1.shape, w2.shape, b2.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="7">
<pre data-code-line-numbers=""><code>(torch.Size([784, 50]), torch.Size([50]), torch.Size([50, 1]), torch.Size([1]))</code></pre>
</div>
</div>
<p>…and create our linear model!</p>
<div id="561a2d3a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> lin(x, w, b): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> w <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> b</span></code></pre></div></div>
</div>
<div id="3a3062ba" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb11" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1">t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> lin(vld_x, w1, b1)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> t.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="9">
<pre data-code-line-numbers=""><code>torch.Size([1000, 50])</code></pre>
</div>
</div>
<div id="042dcb71" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1">vld_x.shape, w1.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="10">
<pre data-code-line-numbers=""><code>(torch.Size([1000, 784]), torch.Size([784, 50]))</code></pre>
</div>
</div>
<div id="f9784748" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb15" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb15-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> fastcore.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">all</span> <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span></span>
<span id="cb15-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> torch.nn.functional <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> F</span>
<span id="cb15-3">test_eq(lin(vld_x, w1, b1), F.linear(vld_x, w1.T, b1))</span></code></pre></div></div>
</div>
<p>Our implementation produces the same outputs as PyTorch’s implementation.</p>
<p>We now need to implement the activation function, which will be the ReLU (rectified linear unit). Any value less than 0 gets clipped to 0. There are multiple ways we can approach doing this, such as using <code>torch.max</code>.</p>

<div class="no-row-height column-margin column-container"><div id="c4ef91cd" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb16" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1">?torch.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span></span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<div class="ansi-escaped-output">
<pre><span class="ansi-red-fg">Docstring:</span>

max(input) -&gt; Tensor



Returns the maximum value of all elements in the ``input`` tensor.



.. warning::

    This function produces deterministic (sub)gradients unlike ``max(dim=0)``



Args:

    input (Tensor): the input tensor.



Example::



    &gt;&gt;&gt; a = torch.randn(1, 3)

    &gt;&gt;&gt; a

    tensor([[ 0.6763,  0.7445, -2.2369]])

    &gt;&gt;&gt; torch.max(a)

    tensor(0.7445)



.. function:: max(input, dim, keepdim=False, *, out=None) -&gt; (Tensor, LongTensor)

   :noindex:



Returns a namedtuple ``(values, indices)`` where ``values`` is the maximum

value of each row of the :attr:`input` tensor in the given dimension

:attr:`dim`. And ``indices`` is the index location of each maximum value found

(argmax).



If ``keepdim`` is ``True``, the output tensors are of the same size

as ``input`` except in the dimension ``dim`` where they are of size 1.

Otherwise, ``dim`` is squeezed (see :func:`torch.squeeze`), resulting

in the output tensors having 1 fewer dimension than ``input``.



.. note:: If there are multiple maximal values in a reduced row then

          the indices of the first maximal value are returned.



Args:

    input (Tensor): the input tensor.

    dim (int): the dimension to reduce.

    keepdim (bool): whether the output tensor has :attr:`dim` retained or not. Default: ``False``.



Keyword args:

    out (tuple, optional): the result tuple of two output tensors (max, max_indices)



Example::



    &gt;&gt;&gt; a = torch.randn(4, 4)

    &gt;&gt;&gt; a

    tensor([[-1.2360, -0.2942, -0.1222,  0.8475],

            [ 1.1949, -1.1127, -2.2379, -0.6702],

            [ 1.5717, -0.9207,  0.1297, -1.8768],

            [-0.6172,  1.0036, -0.6060, -0.2432]])

    &gt;&gt;&gt; torch.max(a, 1)

    torch.return_types.max(values=tensor([0.8475, 1.1949, 1.5717, 1.0036]), indices=tensor([3, 0, 0, 1]))



.. function:: max(input, other, *, out=None) -&gt; Tensor

   :noindex:



See :func:`torch.maximum`.

<span class="ansi-red-fg">Type:</span>      builtin_function_or_method</pre>
</div>
</div>
</div></div><div id="e05b2847" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb17" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb17-1">torch.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(tensor([<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>]), tensor([<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="13">
<pre data-code-line-numbers=""><code>tensor([0, 2, 3, 0])</code></pre>
</div>
</div>
<div id="c4ad1f28" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb19" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb19-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> relu(x): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> torch.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(x, tensor([<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]))</span></code></pre></div></div>
</div>
<p>Another way is to use <code>torch.clamp_min</code>, which is more idiomatic for this case.</p>
<div id="96be5013" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb20" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb20-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> relu(x): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> x.clamp_min(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.</span>)</span></code></pre></div></div>
</div>
<div id="ed94fba6" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb21" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb21-1">t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> lin(vld_x, w1, b1)</span>
<span id="cb21-2">test_eq(relu(t), F.relu(t))</span></code></pre></div></div>
</div>
<p>A single neuron can now be constructed.</p>
<div id="5ce3d71f" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb22" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb22-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> model(xb):</span>
<span id="cb22-2">  l1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> relu(lin(xb, w1, b1))</span>
<span id="cb22-3">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> lin(l1, w2, b2)</span></code></pre></div></div>
</div>
<div id="7f4ea596" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb23" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb23-1">res <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(vld_x)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> res.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="18">
<pre data-code-line-numbers=""><code>torch.Size([1000, 1])</code></pre>
</div>
</div>
</section>
<section id="loss-function" class="level2">
<h2 class="anchored" data-anchor-id="loss-function">Loss Function</h2>
<p>With the forward pass being implemented, it is time to determine the loss. Even though we have a multi-class classification problem at hand, I will use mean squared error for simplicity. Later in this post, I will switch to cross entropy loss.</p>
<p>The Mean Squared Error (MSE) between two vectors can be represented as:</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Ctext%7BMSE%7D%20=%20%5Cfrac%7B%5Csum_%7Bi=1%7D%5E%7Bn%7D%20(y_i%20-%20x_i)%5E2%7D%7Bn%7D%0A"></p>
<p>where <img src="https://latex.codecogs.com/png.latex?x"> and <img src="https://latex.codecogs.com/png.latex?y"> are vectors of length <img src="https://latex.codecogs.com/png.latex?n">, and <img src="https://latex.codecogs.com/png.latex?x_i"> and <img src="https://latex.codecogs.com/png.latex?y_i"> represent the <img src="https://latex.codecogs.com/png.latex?i">-th elements of the vectors.</p>
<div class="callout callout-style-simple callout-note">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>MSE in its most basic form looks like this.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Ctext%7BMSE%7D%20=%20%5Cfrac%7B(y%20-%20x)%5E2%7D%7B1%7D%0A"></p>
<p>If we have multiple data points, then it looks like this.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Ctext%7BMSE%7D%20=%20%5Cfrac%7B(y_1%20-%20x_1)%5E2+(y_2%20-%20x_2)%5E2+(y_3%20-%20x_3)%5E2%7D%7B3%7D%0A"></p>
</div>
</div>
</div>
<p>The tensor holding the predictions and the tensor holding the targets have different shapes. Therefore, there are different ways in which both can be subtracted from each other.</p>
<div id="d4ac5a4b" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb25" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb25-1">res.shape, vld_y.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="19">
<pre data-code-line-numbers=""><code>(torch.Size([1000, 1]), torch.Size([1000]))</code></pre>
</div>
</div>
<div id="0f043f3d" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb27" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb27-1">(vld_y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> res).shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="20">
<pre data-code-line-numbers=""><code>torch.Size([1000, 1000])</code></pre>
</div>
</div>
<div id="88f55df9" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb29" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb29-1">(vld_y[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> res).shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="21">
<pre data-code-line-numbers=""><code>torch.Size([1000, 1])</code></pre>
</div>
</div>
<div id="c4e77f57" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb31" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb31-1">res[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].shape, res.squeeze().shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="22">
<pre data-code-line-numbers=""><code>(torch.Size([1000]), torch.Size([1000]))</code></pre>
</div>
</div>
<div id="3249124b" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb33" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb33-1">(vld_y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> res[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]).shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="23">
<pre data-code-line-numbers=""><code>torch.Size([1000])</code></pre>
</div>
</div>
<p>However, it will be better to add a column to <code>vld_y</code> rather than remove a column from <code>res</code>, so as to keep the shape of all tensors consistent (i.e., all tensors having a row and column, as opposed to some having rows and columns, and others having only a column).</p>
<div id="8ba91cd1" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb35" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb35-1">((vld_y[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> res)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> res.shape[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="24">
<pre data-code-line-numbers=""><code>tensor(717.17)</code></pre>
</div>
</div>
<div id="da5f1ecc" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb37" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb37-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> mse(preds, targs): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> (targs[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> preds).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">pow</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>).mean()</span></code></pre></div></div>
</div>
<div id="13eb4d77" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb38" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb38-1">preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(trn_x)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> mse(preds, trn_y)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="26">
<pre data-code-line-numbers=""><code>tensor(648.87)</code></pre>
</div>
</div>
<div id="0d20d94c" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb40" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb40-1">test_eq(mse(preds, trn_y), F.mse_loss(preds, trn_y[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>]))</span></code></pre></div></div>
</div>
</section>
<section id="backward-pass" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="backward-pass">Backward Pass</h2>
<p>Now comes the backward pass; the pass responsible for computing the gradients of our model’s weights.</p>
<p>For brevity, I will not explain why I compute the gradients the way I do. It can be taken that the way I compute them is due to the result of calculating the derivatives of the foward pass by hand. If you would like to explore how I did so, you can refer to my other blog post, <a href="../../forblog/posts/18_backprop_from_scratch.html">Backpropagation Explained using English Words*</a>.</p>
<p>In short, the derivatives compute to be the following.</p>
<div class="callout callout-style-simple callout-none no-icon">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon no-icon"></i>
</div>
<div class="callout-body-container">
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Balign%7D%0A%20%20%5Cfrac%7B%5Cpartial%20%5Ctext%7BMSE%7D%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%7D%20&amp;=%0A%20%20%20%20%5Cbegin%7Bcases%7D%0A%20%20%20%20%20%200%20&amp;%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%E2%89%A4%200%20%5C%5C%0A%20%20%20%20%20%20%5Cfrac%7B2%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20(%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2%20-%20%5Cvec%7B%5Crm%7By%7D%7D_i)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D%5ET_2%20%5Ccdot%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%5ET%20&amp;%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%3E%200%0A%20%20%20%20%5Cend%7Bcases%7D%20%5C%5C%0A%20%20%5Cfrac%7B%5Cpartial%20%5Ctext%7BMSE%7D%7D%7B%5Cpartial%20b_1%7D%20&amp;=%0A%20%20%20%20%5Cbegin%7Bcases%7D%0A%20%20%20%20%20%200%20&amp;%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%E2%89%A4%200%20%5C%5C%0A%20%20%20%20%20%20%5Cfrac%7B2%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20(%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2%20-%20%5Cvec%7B%5Crm%7By%7D%7D_i)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%5ET%20&amp;%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%3E%200%0A%20%20%20%20%5Cend%7Bcases%7D%20%5C%5C%0A%20%20%5Cfrac%7B%5Cpartial%20%5Ctext%7BMSE%7D%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%7D%20&amp;=%0A%20%20%20%20%5Cbegin%7Bcases%7D%0A%20%20%20%20%20%200%20&amp;%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%E2%89%A4%200%20%5C%5C%0A%20%20%20%20%20%20%5Cfrac%7B2%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20(%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2%20-%20%5Cvec%7B%5Crm%7By%7D%7D_i)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D%5ET_2%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%5ET%20&amp;%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%3E%200%0A%20%20%20%20%5Cend%7Bcases%7D%20%5C%5C%0A%20%20%5Cfrac%7B%5Cpartial%20%5Ctext%7BMSE%7D%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%7D%20&amp;=%20%5Cfrac%7B2%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20(%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2%20-%20%5Cvec%7B%5Crm%7By%7D%7D_i)%20%5Ccdot%20%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5C%5C%0A%20%20%5Cfrac%7B%5Cpartial%20%5Ctext%7BMSE%7D%7D%7B%5Cpartial%20b_2%7D%20&amp;=%20%5Cfrac%7B2%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2%20-%20%5Cvec%7B%5Crm%7By%7D%7D_i%0A%5Cend%7Balign%7D%0A"></p>
</div>
</div>
</div>
<p>When implementing backpropagation, it is better to implement the entire equation in pieces, by storing the result of each intermediate gradient. These intermediate gradients can then be reused to calculate the gradients of another variable.</p>
<p>Let’s prepare the pieces we’ll need and get started.</p>
<div id="973ff5c9" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb41" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb41-1">l1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> relu(lin(trn_x, w1, b1))</span>
<span id="cb41-2">l2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> lin(l1, w2, b2)</span>
<span id="cb41-3">loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> mse(l2, trn_y)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> loss</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="28">
<pre data-code-line-numbers=""><code>tensor(648.87)</code></pre>
</div>
</div>
<section id="w1-gradients" class="level3">
<h3 class="anchored" data-anchor-id="w1-gradients"><code>w1</code> Gradients</h3>
<p>This is the maths to compute the gradients for <code>w1</code>, as also shown above.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%20%20%5Cfrac%7B%5Cpartial%20%5Ctext%7BMSE%7D%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%7D%20=%0A%20%20%20%20%5Cbegin%7Bcases%7D%0A%20%20%20%20%20%200%20&amp;%20%5Ctext%7Bif%20%7D%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%5Cleq%200%20%5C%5C%0A%20%20%20%20%20%20%5Cfrac%7B2%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20(%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2%20-%20%5Cvec%7B%5Crm%7By%7D%7D_i)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D%5ET_2%20%5Ccdot%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%5ET%20&amp;%20%5Ctext%7Bif%20%7D%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%3E%200%0A%20%20%20%20%5Cend%7Bcases%7D%0A"></p>
<div class="callout callout-style-simple callout-note">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>Here, you can see the individual pieces I will compute to implement this equation.</p>
<div class="callout callout-style-simple callout-note no-icon callout-titled">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-1-contents" aria-controls="callout-1" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon no-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Substitutions
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-1" class="callout-1-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Balign%7D%0A%20%20%20%20u_1%20&amp;=%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%5C%5C%0A%20%20%20%20u_2%20&amp;=%20%5Ctext%7Bmax%7D(0,%20u_1)%20%5C%5C%0A%20%20%20%20u_3%20&amp;=%20u_2%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2%20%5C%5C%0A%20%20%20%20u_4%20&amp;=%20%5Cvec%7B%5Crm%7By%7D%7D_i%20-%20u_3%20%5C%5C%0A%20%20%20%20u_5%20&amp;=%20u_4%5E2%0A%5Cend%7Balign%7D%0A"></p>
</div>
</div>
</div>
<div class="callout callout-style-simple callout-note no-icon callout-titled">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-2-contents" aria-controls="callout-2" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon no-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Derivatives of the Substitutions
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-2" class="callout-2-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Balignat%7D%7B4%7D%0A%20%20%5Ctext%7Bgradient%20of%20%7D%20u_4%20&amp;=%20%5Cfrac%7B%5Cpartial%20u_5%7D%7B%5Cpartial%20u_4%7D%20&amp;&amp;=%0A%20%20%5Cfrac%7B%5Cpartial%7D%7B%5Cpartial%20u_4%7D%20u_4%5E2%20&amp;&amp;&amp;=%202u_4%20%5C%5C%0A%20%20%5Ctext%7Bgradient%20of%20%7D%20u_3%20&amp;=%20%5Cfrac%7B%5Cpartial%20u_4%7D%7B%5Cpartial%20u_3%7D%20&amp;&amp;=%20%5Cfrac%7B%5Cpartial%7D%7B%5Cpartial%20u_3%7D%20%5Cvec%7B%5Crm%7By%7D%7D_i%20-%20u_3%20&amp;&amp;&amp;=%20-1%20%5C%5C%0A%20%20%5Ctext%7Bgradient%20of%20%7D%20u_2%20&amp;=%20%5Cfrac%7B%5Cpartial%20u_3%7D%7B%5Cpartial%20u_2%7D%20&amp;&amp;=%20%5Cfrac%7B%5Cpartial%7D%7B%5Cpartial%20u_2%7D%20u_2%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2%20&amp;&amp;&amp;=%20%5Cvec%7B%5Crm%7Bw%7D%7D%5ET_2%20%5C%5C%0A%20%20%5Ctext%7Bgradient%20of%20%7D%20u_1%20&amp;=%20%5Cfrac%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bu%7D%7D_2%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bu%7D%7D_1%7D%20&amp;&amp;=%20%5Cfrac%7B%5Cpartial%7D%7B%5Cpartial%20u_1%7D%20%5Ctext%7Bmax%7D(0,%20u_1)%20&amp;&amp;&amp;=%0A%20%20%20%20%5Cbegin%7Bcases%7D%0A%20%20%20%20%20%200%20&amp;%20%5Cvec%7B%5Crm%7Bu%7D%7D_1%20%E2%89%A4%200%20%5C%5C%0A%20%20%20%20%20%201%20&amp;%20%5Cvec%7B%5Crm%7Bu%7D%7D_1%20%3E%200%0A%20%20%20%20%5Cend%7Bcases%7D%20%5C%5C%0A%20%20%5Ctext%7Bgradient%20of%20%7D%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20&amp;=%20%5Cfrac%7B%5Cpartial%20u_1%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%7D%20&amp;&amp;=%20%5Cfrac%7B%5Cpartial%7D%7B%5Cpartial%20w_1%7D%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20&amp;&amp;&amp;=%20%5Cvec%7B%5Crm%7Bx%7D%7D%5ET_i%0A%5Cend%7Balignat%7D%0A"></p>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="b599542a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb43" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb43-1">diff <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_y[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> l2<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> diff.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="29">
<pre data-code-line-numbers=""><code>torch.Size([1000, 1])</code></pre>
</div>
</div>
<div id="41e75115" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb45" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb45-1">loss.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>n) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> diff<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> loss, loss.g.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="30">
<pre data-code-line-numbers=""><code>(tensor(648.87), torch.Size([1000, 1]))</code></pre>
</div>
</div>
<div id="21ab4c21" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb47" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb47-1">diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> loss.g<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> diff[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>], diff.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="31">
<pre data-code-line-numbers=""><code>(tensor([[-15.34],
         [-33.46],
         [-35.26],
         [ -6.92],
         [-21.55]]),
 torch.Size([1000, 1]))</code></pre>
</div>
</div>
<div id="ef59d269" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb49" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb49-1">(w2.shape, diff.g.shape), (w2.T.shape, diff.g[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>].shape)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="32">
<pre data-code-line-numbers=""><code>((torch.Size([50, 1]), torch.Size([1000, 1])),
 (torch.Size([1, 50]), torch.Size([1000, 1, 1])))</code></pre>
</div>
</div>
<div id="b22495fe" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb51" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb51-1">(diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> w2.T).shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="33">
<pre data-code-line-numbers=""><code>torch.Size([1000, 50])</code></pre>
</div>
</div>
<div id="3cd30ec6" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb53" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb53-1">l2.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> w2.T<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> l2.g.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="34">
<pre data-code-line-numbers=""><code>torch.Size([1000, 50])</code></pre>
</div>
</div>
<div id="063bbf4c" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb55" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb55-1">(l1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="35">
<pre data-code-line-numbers=""><code>tensor([[0., 1., 1.,  ..., 0., 0., 0.],
        [0., 0., 1.,  ..., 1., 0., 0.],
        [1., 1., 1.,  ..., 0., 0., 1.],
        ...,
        [0., 0., 0.,  ..., 0., 1., 0.],
        [1., 1., 0.,  ..., 0., 0., 1.],
        [0., 0., 1.,  ..., 0., 0., 0.]])</code></pre>
</div>
</div>
<div id="4a5f748d" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb57" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb57-1">l1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> l2.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (l1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> l1.g.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="36">
<pre data-code-line-numbers=""><code>torch.Size([1000, 50])</code></pre>
</div>
</div>
<div id="57678cf4" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb59" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb59-1">(l1.g.shape, trn_x.shape), (l1.g[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, :].shape, trn_x[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>].shape)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="37">
<pre data-code-line-numbers=""><code>((torch.Size([1000, 50]), torch.Size([1000, 784])),
 (torch.Size([1000, 1, 50]), torch.Size([1000, 784, 1])))</code></pre>
</div>
</div>
<div id="f4d18936" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb61" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb61-1">w1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tensor([<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>])</span></code></pre></div></div>
</div>
<div id="b05c5821" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb62" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb62-1">w1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (l1.g[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, :] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> trn_x[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>]).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> w1.g.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="39">
<pre data-code-line-numbers=""><code>torch.Size([784, 50])</code></pre>
</div>
</div>
<div id="3ff02e5c" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb64" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb64-1">(w1.shape, w1.g.shape), (w1.g.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(), w1.g.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>())</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="40">
<pre data-code-line-numbers=""><code>((torch.Size([784, 50]), torch.Size([784, 50])),
 (tensor(-17.50), tensor(25.09)))</code></pre>
</div>
</div>
<p>Let’s verify our derivation is correct by comparing it to the gradients computed by PyTorch.</p>
<div id="264b4062" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb66" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb66-1">w1_ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> w1.clone().requires_grad_()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span></code></pre></div></div>
</div>
<div id="e538680b" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb67" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb67-1">l1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> relu(lin(trn_x, w1_, b1))</span>
<span id="cb67-2">l2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> lin(l1, w2, b2)</span>
<span id="cb67-3">loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> mse(l2, trn_y)</span>
<span id="cb67-4">loss.backward()</span></code></pre></div></div>
</div>
<div id="06ceaef0" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb68" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb68-1">w1_.grad</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="43">
<pre data-code-line-numbers=""><code>tensor([[0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.],
        ...,
        [0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.]])</code></pre>
</div>
</div>
<div id="8fd14f57" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb70" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb70-1">(w1.g.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(), w1.g.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>()), (w1_.grad.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(), w1_.grad.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>())</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="44">
<pre data-code-line-numbers=""><code>((tensor(-17.50), tensor(25.09)), (tensor(-17.50), tensor(25.09)))</code></pre>
</div>
</div>
<div id="edad7521" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb72" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb72-1">test_close(w1.g, w1_.grad, eps<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.01</span>)</span></code></pre></div></div>
</div>
<p>It is!</p>
</section>
<section id="b1-gradients" class="level3">
<h3 class="anchored" data-anchor-id="b1-gradients"><code>b1</code> Gradients</h3>
<p>As previously mentioned, I can reuse the computed gradients to calculate the gradients for <img src="https://latex.codecogs.com/png.latex?b_1">. For now though, I will show the entire implemention for easy reference and later, when we will encapsulate the backward pass, I will reuse the already computed gradients.</p>
<div id="8aadf461" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb73" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb73-1">diff <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_y[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> l2</span>
<span id="cb73-2">loss.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>n) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> diff</span>
<span id="cb73-3">diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb73-4">l2.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> w2.T</span>
<span id="cb73-5">l1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> l2.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (l1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>()</span>
<span id="cb73-6">l1.g.shape, b1.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="46">
<pre data-code-line-numbers=""><code>(torch.Size([1000, 50]), torch.Size([50]))</code></pre>
</div>
</div>
<div id="c53ed0cb" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb75" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb75-1">b1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (l1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> b1.g.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="47">
<pre data-code-line-numbers=""><code>torch.Size([50])</code></pre>
</div>
</div>
<div id="5d522fd9" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb77" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb77-1">b1.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(), b1.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="48">
<pre data-code-line-numbers=""><code>(tensor(0.), tensor(0.))</code></pre>
</div>
</div>
</section>
<section id="trn_x-gradients" class="level3">
<h3 class="anchored" data-anchor-id="trn_x-gradients"><code>trn_x</code> Gradients</h3>
<div id="fda30bf9" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb79" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb79-1">diff <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_y[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> l2</span>
<span id="cb79-2">loss.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>n) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> diff</span>
<span id="cb79-3">diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb79-4">l2.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> w2.T</span>
<span id="cb79-5">l1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> l2.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (l1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>()</span>
<span id="cb79-6">l1.g.shape, w1.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="49">
<pre data-code-line-numbers=""><code>(torch.Size([1000, 50]), torch.Size([784, 50]))</code></pre>
</div>
</div>
<div id="3e57d0bc" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb81" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb81-1">trn_x.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> l1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> w1.T</span></code></pre></div></div>
</div>
<div id="3ccca020" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb82" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb82-1">trn_x.g.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(), trn_x.g.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="51">
<pre data-code-line-numbers=""><code>(tensor(-2.85, grad_fn=&lt;MinBackward1&gt;), tensor(2.85, grad_fn=&lt;MaxBackward1&gt;))</code></pre>
</div>
</div>
</section>
<section id="w1-gradients-1" class="level3">
<h3 class="anchored" data-anchor-id="w1-gradients-1"><code>w1</code> Gradients</h3>
<div id="5a370c69" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb84" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb84-1">diff <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_y[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> l2</span>
<span id="cb84-2">loss.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>n) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> diff</span>
<span id="cb84-3">diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb84-4">diff.g.shape, l1.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="52">
<pre data-code-line-numbers=""><code>(torch.Size([1000, 1]), torch.Size([1000, 50]))</code></pre>
</div>
</div>
<div id="ee1419d1" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb86" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb86-1">(diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> l1).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, keepdim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>).T.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="53">
<pre data-code-line-numbers=""><code>torch.Size([50, 1])</code></pre>
</div>
</div>
<div id="e2aaf5da" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb88" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb88-1">(diff.g[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, :] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> l1[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>]).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>).shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="54">
<pre data-code-line-numbers=""><code>torch.Size([50, 1])</code></pre>
</div>
</div>
<div id="2bfbf779" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb90" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb90-1">w2.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (diff.g[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, :] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> l1[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>]).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> w2.g.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="55">
<pre data-code-line-numbers=""><code>torch.Size([50, 1])</code></pre>
</div>
</div>
<div id="e2f8b4fe" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb92" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb92-1">w2.g.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(), w2.g.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="56">
<pre data-code-line-numbers=""><code>(tensor(8.37, grad_fn=&lt;MinBackward1&gt;), tensor(388.44, grad_fn=&lt;MaxBackward1&gt;))</code></pre>
</div>
</div>
</section>
<section id="b2-gradients" class="level3">
<h3 class="anchored" data-anchor-id="b2-gradients"><code>b2</code> Gradients</h3>
<div id="53016ec6" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb94" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb94-1">diff <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_y[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> l2</span>
<span id="cb94-2">loss.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>n) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> diff</span>
<span id="cb94-3">diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb94-4">b2.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb94-5">b2.g.shape, b2.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="57">
<pre data-code-line-numbers=""><code>(torch.Size([1]), torch.Size([1]))</code></pre>
</div>
</div>
</section>
<section id="verify" class="level3 page-columns page-full">
<h3 class="anchored" data-anchor-id="verify">Verify</h3>
<p>Let’s verify our remaining gradients.</p>

<div class="no-row-height column-margin column-container"><div id="461efd95" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb96" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb96-1">w1_, b1_, w2_, b2_, trn_x_ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> w: w.clone.requires_grad_() <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> w <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> [w1, b1, w2, b2, trn_x]]</span></code></pre></div></div>
</div><div class="">
<p>The expression above does not work to create copies. Rather than returning a cloned copy that requires gradients, lambda objects will be returned.</p>
</div></div>
<div id="f9673aa0" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb97" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb97-1">w1_, b1_, w2_, b2_, trn_x_ <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> w: w.clone().requires_grad_(), [w1, b1, w2, b2, trn_x])</span></code></pre></div></div>
</div>
<div id="c17e35e6" class="cell page-columns page-full">

<div class="no-row-height column-margin column-container"><div class="cell-output cell-output-display" data-execution_count="60">
<pre data-code-line-numbers=""><code>tensor([[-2.81, -1.72, -0.97,  ..., -0.29, -1.62, -0.45],
        [-1.77, -0.17,  1.32,  ..., -0.92,  0.76,  2.77],
        [ 0.58,  2.13, -0.98,  ...,  0.41,  1.50,  0.86],
        ...,
        [-0.50, -1.90, -0.10,  ..., -1.61,  0.78, -0.09],
        [ 0.89,  0.50,  1.21,  ...,  0.93, -0.37, -0.85],
        [ 0.57, -0.50, -1.47,  ...,  0.72,  1.64, -0.85]], requires_grad=True)</code></pre>
</div></div></div>
<div id="77b15490" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb99" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb99-1">w1_</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="61">
<pre data-code-line-numbers=""><code>tensor([[-2.81, -1.72, -0.97,  ..., -0.29, -1.62, -0.45],
        [-1.77, -0.17,  1.32,  ..., -0.92,  0.76,  2.77],
        [ 0.58,  2.13, -0.98,  ...,  0.41,  1.50,  0.86],
        ...,
        [-0.50, -1.90, -0.10,  ..., -1.61,  0.78, -0.09],
        [ 0.89,  0.50,  1.21,  ...,  0.93, -0.37, -0.85],
        [ 0.57, -0.50, -1.47,  ...,  0.72,  1.64, -0.85]], requires_grad=True)</code></pre>
</div>
</div>
<div id="0915ac25" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb101" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb101-1">l1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> relu(lin(trn_x_, w1_, b1_))</span>
<span id="cb101-2">l2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> lin(l1, w2_, b2_)</span>
<span id="cb101-3">loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> mse(l2, trn_y)</span>
<span id="cb101-4">loss.backward()</span></code></pre></div></div>
</div>
<div id="89781f9c" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb102" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb102-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> a, b <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>((w1, b1, w2, b2, trn_x), (w1_, b1_, w2_, b2_, trn_x_)): test_close(a.g, b.grad, eps<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-2</span>)</span></code></pre></div></div>
</div>
<p>All comparisons passed!</p>
</section>
</section>
<section id="encapsulate" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="encapsulate">Encapsulate</h2>
<p>Now that we have the forward and backward passes sorted, let us cohesively bring them together.</p>
<div id="a9dd4ae3" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb103" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb103-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> forward(inps, targs):</span>
<span id="cb103-2">  l1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> relu(lin(inps, w1, b1))</span>
<span id="cb103-3">  l2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> lin(l1, w2, b2)</span>
<span id="cb103-4">  loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> mse(l2, targs)</span>
<span id="cb103-5">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> l1, l2, loss</span>
<span id="cb103-6"></span>
<span id="cb103-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> backward(inps, targs, l1, l2, loss):</span>
<span id="cb103-8">  diff <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> targs[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> l2</span>
<span id="cb103-9">  loss.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> n) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> diff</span>
<span id="cb103-10">  diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb103-11"></span>
<span id="cb103-12">  w2.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (diff.g[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, :] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> l1[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>]).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb103-13">  b2.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb103-14"></span>
<span id="cb103-15">  l2.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> w2.T</span>
<span id="cb103-16">  l1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> l2.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (l1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>()</span>
<span id="cb103-17"></span>
<span id="cb103-18">  w1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (l1.g[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, :] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> trn_x[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>]).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb103-19">  b1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (l1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb103-20"></span>
<span id="cb103-21">  inps.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> l1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> w1.T</span></code></pre></div></div>
</div>
<div id="7029da35" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb104" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb104-1">l1, l2, loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> forward(trn_x, trn_y)</span>
<span id="cb104-2">backward(trn_x, trn_y, l1, l2, loss)</span></code></pre></div></div>
</div>
<div id="9ee415ef" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb105" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb105-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> comp_grads(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>ws):</span>
<span id="cb105-2">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> a, b <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(ws, (w1_, b1_, w2_, b2_, trn_x_)): test_close(a.g, b.grad, eps<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-2</span>)</span></code></pre></div></div>
</div>
<div id="8ea0a281" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb106" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb106-1">comp_grads(w1, b1, w2, b2, trn_x)</span></code></pre></div></div>
</div>
<p>The <code>backward</code> function can be further refactored by taking the gradient computations of the linear layers common.</p>
<div id="79c02c05" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb107" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb107-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> backward(inps, targs, l1, l2, loss):</span>
<span id="cb107-2">  diff <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> targs[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> l2</span>
<span id="cb107-3">  loss.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>n) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> diff</span>
<span id="cb107-4">  diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb107-5"></span>
<span id="cb107-6">  lin_grad(l1, diff, w2, b2)</span>
<span id="cb107-7">  l2.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> w2.T</span>
<span id="cb107-8">  l1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> l2.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (l1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>()</span>
<span id="cb107-9">  lin_grad(inps, l1, w1, b1)</span>
<span id="cb107-10"></span>
<span id="cb107-11"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> lin_grad(inp, out, w, b):</span>
<span id="cb107-12">  inp.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> out.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> w.T</span>
<span id="cb107-13">  w.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (out.g[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, :] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> inp[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>]).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb107-14">  b.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (out.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span></code></pre></div></div>
</div>

<div class="no-row-height column-margin column-container"><div class="">
<p>Previous implementation.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb108" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode py code-with-copy"><code class="sourceCode python"><span id="cb108-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> backward(inps, targs, l1, l2, loss):</span>
<span id="cb108-2">  diff <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> targs[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> l2</span>
<span id="cb108-3">  loss.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> n) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> diff</span>
<span id="cb108-4">  diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb108-5"></span>
<span id="cb108-6">  w2.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (diff.g[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, :] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> l1[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>]).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb108-7">  b2.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb108-8"></span>
<span id="cb108-9">  l2.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> w2.T</span>
<span id="cb108-10">  l1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> l2.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (l1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>()</span>
<span id="cb108-11"></span>
<span id="cb108-12">  w1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (l1.g[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, :] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> trn_x[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>]).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb108-13">  b1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (l1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb108-14"></span>
<span id="cb108-15">  inps.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> l1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> w1.T</span></code></pre></div></div>
</div></div><div id="2ea05601" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb109" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb109-1">backward(trn_x, trn_y, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>forward(trn_x, trn_y))</span></code></pre></div></div>
</div>
<div id="b706640f" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb110" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb110-1">comp_grads(w1, b1, w2, b2, trn_x)</span></code></pre></div></div>
</div>
<section id="class" class="level3">
<h3 class="anchored" data-anchor-id="class">Class</h3>
<p>Currently, we have functions that each separately handle a part of the network. For instance, <code>mse</code> only computes its respective portion of the forward pass: the mean squared error. <code>backward</code> is a separate function that handles the backward pass for all pieces of the network.</p>
<p>Let us change how this works, so each piece of the network also handles its respective backward pass. This means, <code>mse</code> will have the ability to compute both its forward pass and backward pass.</p>
<div id="2f6efbf8" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb111" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb111-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> MSE:</span>
<span id="cb111-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__call__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, inp, targs):</span>
<span id="cb111-3">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.inp,<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.targs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> inp,targs</span>
<span id="cb111-4">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.out <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (inp[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> targs).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">pow</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>).mean()</span>
<span id="cb111-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.out</span>
<span id="cb111-6">  </span>
<span id="cb111-7">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> backward(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>): <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.inp.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.inp.shape[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.inp[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.targs)[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>]</span></code></pre></div></div>
</div>
<div id="6353721e" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb112" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb112-1">test_eq(MSE()(preds, trn_y), mse(preds, trn_y))</span></code></pre></div></div>
</div>
<div id="839fc3c4" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb113" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb113-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Lin:</span>
<span id="cb113-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, w, b): <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.w,<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> w,b</span>
<span id="cb113-3"></span>
<span id="cb113-4">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__call__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, inp):</span>
<span id="cb113-5">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.inp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> inp</span>
<span id="cb113-6">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.out <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.inp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.w <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.b</span>
<span id="cb113-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.out</span>
<span id="cb113-8">  </span>
<span id="cb113-9">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> backward(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb113-10">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.inp.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.out.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.w.T</span>
<span id="cb113-11">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.w.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.out.g[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, :] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.inp[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>]).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb113-12">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.b.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.out.g.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span></code></pre></div></div>
</div>
<div id="9c86d32b" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb114" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb114-1">test_eq(Lin(w1, b1)(trn_x), lin(trn_x, w1, b1))</span></code></pre></div></div>
</div>
<div id="a1dc8175" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb115" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb115-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> ReLU:</span>
<span id="cb115-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__call__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, inp):</span>
<span id="cb115-3">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.inp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> inp</span>
<span id="cb115-4">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.out <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.inp.clamp_min(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.</span>)</span>
<span id="cb115-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.out</span>
<span id="cb115-6">  </span>
<span id="cb115-7">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> backward(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>): <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.inp.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.out.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.inp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>()</span></code></pre></div></div>
</div>
<div id="0c657d4a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb116" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb116-1">test_eq(ReLU()(l1), relu(l1))</span></code></pre></div></div>
</div>
<div id="0d323423" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb117" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb117-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Model:</span>
<span id="cb117-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, w1, b1, w2, b2):</span>
<span id="cb117-3">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.layers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [Lin(w1, b1), ReLU(), Lin(w2, b2)]</span>
<span id="cb117-4">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> MSE()</span>
<span id="cb117-5">  </span>
<span id="cb117-6">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__call__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, inp, targs):</span>
<span id="cb117-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> l <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.layers: inp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> l(inp)</span>
<span id="cb117-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.loss(inp, targs)</span>
<span id="cb117-9">  </span>
<span id="cb117-10">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> backward(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb117-11">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.loss.backward()</span>
<span id="cb117-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> l <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.layers[::<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]: l.backward()</span></code></pre></div></div>
</div>
<div id="c9da2d17" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb118" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb118-1">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Model(w1, b1, w2, b2)</span>
<span id="cb118-2">l <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(trn_x, trn_y)</span>
<span id="cb118-3">model.backward()</span></code></pre></div></div>
</div>
<div id="5d58ef57" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb119" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb119-1">comp_grads(w1, b1, w2, b2, trn_x)</span></code></pre></div></div>
</div>
</section>
<section id="super-class" class="level3">
<h3 class="anchored" data-anchor-id="super-class">Super Class</h3>
<p>The classes we have created have common functionality, meaning their is still room for further refactoring. In particular, all the classes store the forward pass arguments as attributes if needed, have a <code>__call__</code> dunder method that exectutes the forward pass, and a <code>backward</code> method for the backward pass.</p>
<div id="2503dd1a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb120" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb120-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Module():</span>
<span id="cb120-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__call__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args):</span>
<span id="cb120-3">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.args <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> args</span>
<span id="cb120-4">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.out <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.forward(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>args)</span>
<span id="cb120-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.out</span>
<span id="cb120-6">  </span>
<span id="cb120-7">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> forward(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">Exception</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Forward pass not implemented'</span>)</span>
<span id="cb120-8">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> backward(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>): <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.bwd(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.out, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.args)</span>
<span id="cb120-9">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> bwd(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">raise</span> <span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">Exception</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Backward pass not implemented.'</span>)</span></code></pre></div></div>
</div>
<div id="dc6dba97" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb121" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb121-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> MSE(Module):</span>
<span id="cb121-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> forward(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, inp, targs): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> (inp[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> targs).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">pow</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>).mean()</span>
<span id="cb121-3">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> bwd(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, out, inp, targs): inp.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> inp.shape[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (inp[:, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> targs)[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>]</span></code></pre></div></div>
</div>
<div id="dea64262" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb122" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb122-1">test_eq(MSE()(preds, trn_y), mse(preds, trn_y))</span></code></pre></div></div>
</div>
<div id="41ef6a88" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb123" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb123-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Lin(Module):</span>
<span id="cb123-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, w, b): <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.w,<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> w,b</span>
<span id="cb123-3">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> forward(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, inp): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> inp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.w <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.b</span>
<span id="cb123-4">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> bwd(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, out, inp):</span>
<span id="cb123-5">    inp.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> out.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.w.T</span>
<span id="cb123-6">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.w.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (out.g[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, :] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> inp[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>]).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb123-7">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.b.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> out.g.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)</span>
<span id="cb123-8">    </span></code></pre></div></div>
</div>
<div id="1a65bbd7" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb124" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb124-1">test_eq(Lin(w1, b1)(trn_x), lin(trn_x, w1, b1))</span></code></pre></div></div>
</div>
<div id="37e2f989" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb125" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb125-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> ReLU(Module):</span>
<span id="cb125-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> forward(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, inp): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> inp.clamp_min(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.</span>)</span>
<span id="cb125-3">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> bwd(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, out, inp): inp.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> out.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (inp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>()</span></code></pre></div></div>
</div>
<div id="7b2e0221" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb126" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb126-1">test_eq(ReLU()(l1), relu(l1))</span></code></pre></div></div>
</div>
<div id="b52c153b" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb127" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb127-1">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Model(w1, b1, w2, b2)</span>
<span id="cb127-2">loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(trn_x, trn_y)</span>
<span id="cb127-3">model.backward()</span></code></pre></div></div>
</div>
<div id="daf7cb70" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb128" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb128-1">comp_grads(w1, b1, w2, b2)</span></code></pre></div></div>
</div>
<p>And with that, this is the basic underlying paradigm in which PyTorch implements its components.</p>
<p>So let us now directly use PyTorch’s <code>nn.Module</code> to handle our components. There is an added benefit that <code>nn.Module</code> automatically keeps track of our gradients, so we do not need to implement the backward pass.</p>
</section>
<section id="pytorchs-nn.module" class="level3">
<h3 class="anchored" data-anchor-id="pytorchs-nn.module">PyTorch’s <code>nn.Module</code></h3>
<div id="09774b8b" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb129" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb129-1">w1.shape, n, m, c, b1.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="89">
<pre data-code-line-numbers=""><code>(torch.Size([784, 50]), 1000, 784, tensor(10), torch.Size([50]))</code></pre>
</div>
</div>
<div id="b55a597c" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb131" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb131-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> torch <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> nn</span>
<span id="cb131-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Linear(nn.Module):</span>
<span id="cb131-3">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, n_inps, n_outs):</span>
<span id="cb131-4">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">super</span>().<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>()</span>
<span id="cb131-5">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.w <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.randn(n_inps, n_outs).requires_grad_()</span>
<span id="cb131-6">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> torch.randn(n_outs).requires_grad_()</span>
<span id="cb131-7">  </span>
<span id="cb131-8">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> forward(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, inp): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> inp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.w <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.b</span></code></pre></div></div>
</div>
<div id="b8014566" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb132" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb132-1">F <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.functional</span>
<span id="cb132-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Model(nn.Module):</span>
<span id="cb132-3">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, n_inp, nh, n_out):</span>
<span id="cb132-4">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">super</span>().<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>()</span>
<span id="cb132-5">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.layers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [Linear(n_inp, nh), nn.ReLU(), Linear(nh, n_out)]</span>
<span id="cb132-6">  </span>
<span id="cb132-7">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__call__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, inp, targ):</span>
<span id="cb132-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> l <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.layers: inp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> l(inp)</span>
<span id="cb132-9">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> F.mse_loss(inp, targ[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>])</span></code></pre></div></div>
</div>
<div id="b665f717" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb133" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb133-1">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Model(m, nh, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb133-2">loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(trn_x, trn_y.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>())</span>
<span id="cb133-3">loss.backward()</span></code></pre></div></div>
</div>
<div id="dc96b4ab" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb134" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb134-1">model.layers</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="93">
<pre data-code-line-numbers=""><code>[Linear(), ReLU(), Linear()]</code></pre>
</div>
</div>
<div id="d817b288" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb136" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb136-1">l0 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model.layers[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> l0.b.grad</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="94">
<pre data-code-line-numbers=""><code>tensor([ 42.11, -25.91,   0.15,  15.73, -16.16,  41.61,  13.73,  81.32,  -8.91,  55.30, -14.12, -82.24,  12.02, -27.58,  -9.48, -90.85,
        -25.55,  34.89,  -0.68, -14.24,   4.73,  49.70, -27.02,  19.55,  10.14,  38.86,  30.55,  74.17,   2.15,  -2.62, -37.11,  14.04,
        -12.12,   0.89,  -0.99,  -6.29,  -1.15,  12.26,  -9.73,  -4.13,  -1.53,   1.67,   1.34,  -9.78,  20.50,   7.30,  62.45,   5.94,
         -3.28, -18.14])</code></pre>
</div>
</div>
<hr>
</section>
</section>
<section id="cross-entropy-loss" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="cross-entropy-loss">Cross Entropy Loss</h2>
<p>Let’s now implement a much more appropriate loss function for our multi-target problem: cross entropy loss.</p>
<div id="ee9c6aa9" class="cell">
<details class="code-fold">
<summary>Redefinition of <code>Model</code>, but without with loss function.</summary>
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb138" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb138-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Model(nn.Module):</span>
<span id="cb138-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, n_inps, nh, n_outs):</span>
<span id="cb138-3">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">super</span>().<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>()</span>
<span id="cb138-4">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.layers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [nn.Linear(n_inps, nh), nn.ReLU(), nn.Linear(nh, n_outs)]</span>
<span id="cb138-5"></span>
<span id="cb138-6">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__call__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, x):</span>
<span id="cb138-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> l <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.layers: x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> l(x)</span>
<span id="cb138-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> x</span></code></pre></div></div>
</details>
</div>
<div id="1a42ab37" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb139" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb139-1">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Model(m, nh, c)</span>
<span id="cb139-2">preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(trn_x)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> preds.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="96">
<pre data-code-line-numbers=""><code>torch.Size([1000, 10])</code></pre>
</div>
</div>
<p>As I have defined <a href="../../dictionary/terms/cross_entropy_loss.html">here</a>, cross entropy loss simply involves taking the logarithm of the softmax function, and multiplying the results with the <a href="../../dictionary/terms/one_hot_encoding.html">one hot encoded</a> targets.</p>
<p><a href="../../dictionary/terms/softmax.html">Softmax</a>, a multi-class generalization of the sigmoid function, involves taking the exponent of each prediction, and dividing each resulting value with the sum of all predictions to the exponent.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Ctext%7BS%7D(y_i)%20=%20%5Cfrac%7Be%5E%7By_i%7D%7D%7B%5Csum_%7Bj%7D%20e%5E%7By_j%7D%7D%0A"></p>
<div class="callout callout-style-simple callout-note callout-titled">
<div class="callout-header d-flex align-content-center">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Sigmoid Function Definition
</div>
</div>
<div class="callout-body-container callout-body">
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Csigma(y)%20=%20%5Cfrac%7B1%7D%7B1%20+%20e%5E%7B-y%7D%7D%0A"></p>
</div>
</div>
<p>Let’s begin by first taking the logarithm of the softmax function.</p>
<div id="435815c8" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb141" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb141-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> log_softmax(x): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> ((x.exp() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> x.exp().<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, keepdim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>))).log()</span>
<span id="cb141-2">log_softmax(preds)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="97">
<pre data-code-line-numbers=""><code>tensor([[-2.40, -2.33, -2.25,  ..., -2.33, -2.40, -2.34],
        [-2.37, -2.44, -2.21,  ..., -2.30, -2.34, -2.28],
        [-2.37, -2.45, -2.16,  ..., -2.24, -2.40, -2.40],
        ...,
        [-2.36, -2.45, -2.20,  ..., -2.24, -2.39, -2.37],
        [-2.34, -2.41, -2.28,  ..., -2.20, -2.53, -2.25],
        [-2.43, -2.37, -2.21,  ..., -2.26, -2.40, -2.37]], grad_fn=&lt;LogBackward0&gt;)</code></pre>
</div>
</div>
<div id="15864eac" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb143" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb143-1">F.log_softmax(preds, dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="98">
<pre data-code-line-numbers=""><code>tensor([[-2.40, -2.33, -2.25,  ..., -2.33, -2.40, -2.34],
        [-2.37, -2.44, -2.21,  ..., -2.30, -2.34, -2.28],
        [-2.37, -2.45, -2.16,  ..., -2.24, -2.40, -2.40],
        ...,
        [-2.36, -2.45, -2.20,  ..., -2.24, -2.39, -2.37],
        [-2.34, -2.41, -2.28,  ..., -2.20, -2.53, -2.25],
        [-2.43, -2.37, -2.21,  ..., -2.26, -2.40, -2.37]], grad_fn=&lt;LogSoftmaxBackward0&gt;)</code></pre>
</div>
</div>
<div id="9407bbee" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb145" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb145-1">test_close(log_softmax(preds).detach(), F.log_softmax(preds, dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).detach())</span></code></pre></div></div>
</div>
<p>Our implementation involves division. According to the rule, <img src="https://latex.codecogs.com/png.latex?%5Clg%5Cleft(%5Cfrac%7Ba%7D%7Bb%7D%5Cright)%20=%20%5Clg(a)%20-%20%5Clg(b)">, we can simplify our computation by subtracting the numerators and denominators instead.</p>
<div id="dbc5bed2" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb146" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb146-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> log_softmax(x): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> x.exp().log() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> x.exp().<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, keepdim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>).log()</span></code></pre></div></div>
</div>
<div id="65a62b5c" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb147" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb147-1">log_softmax(preds)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="101">
<pre data-code-line-numbers=""><code>tensor([[-2.40, -2.33, -2.25,  ..., -2.33, -2.40, -2.34],
        [-2.37, -2.44, -2.21,  ..., -2.30, -2.34, -2.28],
        [-2.37, -2.45, -2.16,  ..., -2.24, -2.40, -2.40],
        ...,
        [-2.36, -2.45, -2.20,  ..., -2.24, -2.39, -2.37],
        [-2.34, -2.41, -2.28,  ..., -2.20, -2.53, -2.25],
        [-2.43, -2.37, -2.21,  ..., -2.26, -2.40, -2.37]], grad_fn=&lt;SubBackward0&gt;)</code></pre>
</div>
</div>
<p>Our implementation has an issue though: it is unstable. Anything involving exponents is inherently unstable. Have a large enough value, and we converge to infinity relatively quickly.</p>
<div id="254184c0" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb149" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb149-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> x <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">101</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>): <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'e^</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">=</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>torch<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>exp(tensor(x))<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>e^0=1.0
e^10=22026.46484375
e^20=485165184.0
e^30=10686474223616.0
e^40=2.353852703404196e+17
e^50=5.184705457665547e+21
e^60=1.1420073962419164e+26
e^70=2.515438700355918e+30
e^80=5.540622484676759e+34
e^90=inf
e^100=inf</code></pre>
</div>
</div>
<p>Fortunately, there is trick to overcoming this known as the LogSumExp simplification.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Clg%5Cleft(%5Csum%5En_%7Bj=1%7D%20e%5E%7Bx_j%7D%5Cright)%20=%20%5Clg%5Cleft(e%5Ea%20%5Csum%5En_%7Bj=1%7D%20%5Cfrac%7Be%5E%7Bx_j%7D%7D%7Be%5Ea%7D%5Cright)%20=%20%5Clg%5Cleft(e%5Ea%20%5Csum%5En_%7Bj=1%7D%20e%5E%7Bx_j%20-%20a%7D%5Cright)%20=%20a%20+%20%5Clg%5Cleft(%5Csum%5En_%7Bj=1%7D%20e%5E%7Bx_j%20-%20a%7D%5Cright)%0A"></p>
<p><img src="https://latex.codecogs.com/png.latex?a"> is the largest element in <img src="https://latex.codecogs.com/png.latex?x">.</p>
<p>To begin, we need to get the largest value in each sample.</p>
<div id="0c6ef961" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb151" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb151-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> preds.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>.shape, preds.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="103">
<pre data-code-line-numbers=""><code>(torch.Size([1000]), torch.Size([1000, 10]))</code></pre>
</div>
</div>

<div class="no-row-height column-margin column-container"><div id="38f99cd0" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb153" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb153-1">?torch.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span></span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<div class="ansi-escaped-output">
<pre><span class="ansi-red-fg">Docstring:</span>

max(input) -&gt; Tensor



Returns the maximum value of all elements in the ``input`` tensor.



.. warning::

    This function produces deterministic (sub)gradients unlike ``max(dim=0)``



Args:

    input (Tensor): the input tensor.



Example::



    &gt;&gt;&gt; a = torch.randn(1, 3)

    &gt;&gt;&gt; a

    tensor([[ 0.6763,  0.7445, -2.2369]])

    &gt;&gt;&gt; torch.max(a)

    tensor(0.7445)



.. function:: max(input, dim, keepdim=False, *, out=None) -&gt; (Tensor, LongTensor)

   :noindex:



Returns a namedtuple ``(values, indices)`` where ``values`` is the maximum

value of each row of the :attr:`input` tensor in the given dimension

:attr:`dim`. And ``indices`` is the index location of each maximum value found

(argmax).



If ``keepdim`` is ``True``, the output tensors are of the same size

as ``input`` except in the dimension ``dim`` where they are of size 1.

Otherwise, ``dim`` is squeezed (see :func:`torch.squeeze`), resulting

in the output tensors having 1 fewer dimension than ``input``.



.. note:: If there are multiple maximal values in a reduced row then

          the indices of the first maximal value are returned.



Args:

    input (Tensor): the input tensor.

    dim (int): the dimension to reduce.

    keepdim (bool): whether the output tensor has :attr:`dim` retained or not. Default: ``False``.



Keyword args:

    out (tuple, optional): the result tuple of two output tensors (max, max_indices)



Example::



    &gt;&gt;&gt; a = torch.randn(4, 4)

    &gt;&gt;&gt; a

    tensor([[-1.2360, -0.2942, -0.1222,  0.8475],

            [ 1.1949, -1.1127, -2.2379, -0.6702],

            [ 1.5717, -0.9207,  0.1297, -1.8768],

            [-0.6172,  1.0036, -0.6060, -0.2432]])

    &gt;&gt;&gt; torch.max(a, 1)

    torch.return_types.max(values=tensor([0.8475, 1.1949, 1.5717, 1.0036]), indices=tensor([3, 0, 0, 1]))



.. function:: max(input, other, *, out=None) -&gt; Tensor

   :noindex:



See :func:`torch.maximum`.

<span class="ansi-red-fg">Type:</span>      builtin_function_or_method</pre>
</div>
</div>
</div></div><p>Then we can simply implement the rest of the algorithm.</p>
<div id="4b039783" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb154" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb154-1">(preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>]).shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="105">
<pre data-code-line-numbers=""><code>torch.Size([1000, 10])</code></pre>
</div>
</div>
<div id="72fe79a8" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb156" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb156-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Output hidden to prevent endless scrolling.</span></span>
<span id="cb156-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>]).exp().<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, keepdim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>).log()</span></code></pre></div></div>
</div>
<div id="9330c312" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb157" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb157-1">test_close(torch.exp(preds).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, keepdim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>).log(), <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>]).exp().<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, keepdim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>).log())</span></code></pre></div></div>
</div>
<div id="4465bac5" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb158" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb158-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> logsumexp(x):</span>
<span id="cb158-2">  <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> x.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span>
<span id="cb158-3">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>]).exp().<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, keepdim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>).log()</span></code></pre></div></div>
</div>
<div id="ee462b01" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb159" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb159-1">logsumexp(preds).shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="109">
<pre data-code-line-numbers=""><code>torch.Size([1000, 1])</code></pre>
</div>
</div>
<div id="79ea2af6" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb161" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb161-1">test_close(logsumexp(preds), preds.logsumexp(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>])</span></code></pre></div></div>
</div>
<p>Let’s compare how quicker our new implemenation is compared to the previous one.</p>
<div id="4dd29751" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb162" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb162-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>timeit log_softmax(preds)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>337 µs ± 75.8 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)</code></pre>
</div>
</div>
<div id="8d1d926e" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb164" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb164-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> log_softmax(x): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> logsumexp(x)</span></code></pre></div></div>
</div>
<div id="dd5680bf" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb165" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb165-1">log_softmax(preds).shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="113">
<pre data-code-line-numbers=""><code>torch.Size([1000, 10])</code></pre>
</div>
</div>
<div id="a6263e4c" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb167" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb167-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>timeit log_softmax(preds)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>190 µs ± 56 µs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)</code></pre>
</div>
</div>
<p><em>Much</em> faster!</p>
<p>All that is left now is to multiply our softmax predictions with the one hot encoded targets, and sum the resulting vector. However, due to the nature of our targets, we can employ a nifty trick that removes the need to create a tensor of one hot encoded targets: integer array indexing.</p>
<section id="integer-array-indexing" class="level3">
<h3 class="anchored" data-anchor-id="integer-array-indexing">Integer Array Indexing</h3>
<div id="b3cc433f" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb169" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb169-1">t <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tensor([[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>], [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>], [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>]])<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> t</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="115">
<pre data-code-line-numbers=""><code>tensor([[1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]])</code></pre>
</div>
</div>
<p>A fancy name for a simple concept, integer array indexing allows one to access elements in a tensor by simply specifing lists of indices.</p>
<div id="60221bdb" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb171" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb171-1">t[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>], [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="116">
<pre data-code-line-numbers=""><code>tensor([1, 5, 9])</code></pre>
</div>
</div>
<p>It is best to think of the tensor as a grid of coordinates, with the first coordinate representing the row, and the second coordinate representing the column. Elements 1, 5, and 9 are at (0, 0), (1, 1), and (2, 2).</p>
<p>1, 6, and 8 are at (0, 0), (1, 2), and (2, 1)</p>
<div id="f8eaea7a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb173" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb173-1">t[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>], [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="117">
<pre data-code-line-numbers=""><code>tensor([1, 6, 8])</code></pre>
</div>
</div>
<p>3 and 8 are at (0, 2) and (2, 1).</p>
<div id="7e677521" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb175" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb175-1">t[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>], [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="118">
<pre data-code-line-numbers=""><code>tensor([3, 8])</code></pre>
</div>
</div>
<p>Our targets consist of the integers from 0 to 9. Each row, or sample, in our predictions tensor represents a set of probabilites for each target.</p>
<p>This means we can directly access the prediction for the correct target through integer array indexing.</p>
<div id="8a8fc790" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb177" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb177-1">trn_y[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="119">
<pre data-code-line-numbers=""><code>tensor([5, 0, 4])</code></pre>
</div>
</div>
<p>The targets for the first three samples are 5, 0, and, 4. Instead of manually specifying the targets when obtaining the predictions for the first three samples…</p>
<div id="af742972" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb179" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb179-1">sm_preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> log_softmax(preds)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> sm_preds.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="120">
<pre data-code-line-numbers=""><code>torch.Size([1000, 10])</code></pre>
</div>
</div>
<div id="c2c88d2c" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb181" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb181-1">sm_preds[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>], sm_preds[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], sm_preds[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="121">
<pre data-code-line-numbers=""><code>(tensor(-2.27, grad_fn=&lt;SelectBackward0&gt;),
 tensor(-2.37, grad_fn=&lt;SelectBackward0&gt;),
 tensor(-2.26, grad_fn=&lt;SelectBackward0&gt;))</code></pre>
</div>
</div>
<p>…we can use the targets themselves to directly obtain our predictions.</p>
<div id="c6c0ea14" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb183" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb183-1">sm_preds[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>], trn_y[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>]]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="122">
<pre data-code-line-numbers=""><code>tensor([-2.27, -2.37, -2.26], grad_fn=&lt;IndexBackward0&gt;)</code></pre>
</div>
</div>
<p>And now, our implementation can be completed.</p>
<div id="515acf38" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb185" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb185-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> nll(preds, targs): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>preds[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(targs.shape[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]), targs].mean()</span></code></pre></div></div>
</div>
<div id="52ffefbc" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb186" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb186-1">loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nll(sm_preds, trn_y)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> loss</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="124">
<pre data-code-line-numbers=""><code>tensor(2.30, grad_fn=&lt;NegBackward0&gt;)</code></pre>
</div>
</div>
<div id="8f041e05" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-124" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-annotation-code code-with-copy code-annotated"><code class="sourceCode python"><a class="code-annotation-anchor" data-target-cell="annotated-cell-124" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-124-1" class="code-annotation-target">test_close(F.nll_loss(F.log_softmax(preds, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), trn_y), loss, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">1e-3</span>)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-124" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-124" data-code-lines="1" data-code-annotation="1">The difference between <code>F.cross_entropy</code> and <code>F.nll_loss</code> is that the former expects the input to be the raw model outputs, where as the latter expects the input to already be logarithmic probabilities. It can be said that <code>F.nll_loss</code> computes cross entropy loss by starting at an intemediary step.</span>
</dd>
</dl>
</div>
</div>
</section>
</section>
<section id="basic-training-loop" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="basic-training-loop">Basic Training Loop</h2>
<p>Okay, now we have all the components of a machine that is the neural network:</p>
<ul>
<li>the linear function,</li>
<li>the activation function,</li>
<li>the loss function,</li>
<li>and the backward pass.</li>
</ul>
<p>It is time to get the machine up and running as a whole. It’s time to get the training loop looping.</p>
<div class="grid">
<div class="g-col-4">

</div>
<div class="g-col-4">
<div class="cell" data-layout-align="default">
<div class="cell-output-display">
<div>
<p></p><figure class="figure"><p></p>
<div>
<pre class="mermaid mermaid-js">graph TB
  A[Load Data] --&gt; B[Make Predictions] --&gt; C[Compute Loss] --&gt; D[Compute Gradients] --&gt; E[Update Weights] --&gt; F[Compute Metric] --&gt; A
</pre>
</div>
<p></p></figure><p></p>
</div>
</div>
</div>
</div>
<div class="g-col-4">

</div>
</div>
<div id="5ab96b19" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb188" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb188-1">loss_func <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> F.cross_entropy</span></code></pre></div></div>
</div>
<div id="2d978b8d" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb189" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb189-1">bs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span></span>
<span id="cb189-2">xb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_x[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:bs]</span>
<span id="cb189-3">preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(xb)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> preds[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>], preds.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="127">
<pre data-code-line-numbers=""><code>(tensor([-0.08, -0.01,  0.08,  0.11, -0.02,  0.06,  0.13, -0.00, -0.08, -0.01], grad_fn=&lt;SelectBackward0&gt;),
 torch.Size([50, 10]))</code></pre>
</div>
</div>
<div id="4d2c9f5d" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb191" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb191-1">yb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_y[:bs]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> yb</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="128">
<pre data-code-line-numbers=""><code>tensor([5, 0, 4, 1, 9, 2, 1, 3, 1, 4, 3, 5, 3, 6, 1, 7, 2, 8, 6, 9, 4, 0, 9, 1, 1, 2, 4, 3, 2, 7, 3, 8, 6, 9, 0, 5, 6, 0, 7, 6, 1, 8, 7, 9,
        3, 9, 8, 5, 9, 3])</code></pre>
</div>
</div>
<div id="9707c1b9" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb193" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb193-1">loss_func(preds, yb)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="129">
<pre data-code-line-numbers=""><code>tensor(2.30, grad_fn=&lt;NllLossBackward0&gt;)</code></pre>
</div>
</div>
<p>We’ll use <a href="../../dictionary/terms/accuracy.html">accuracy</a> as our metric.</p>
<div id="e174a394" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb195" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb195-1">preds.argmax(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="130">
<pre data-code-line-numbers=""><code>tensor([6, 2, 2, 2, 5, 2, 5, 2, 5, 2, 2, 2, 3, 2, 5, 5, 2, 2, 2, 5, 6, 3, 5, 2, 5, 2, 2, 3, 3, 2, 2, 2, 5, 2, 2, 2, 2, 2, 2, 2, 5, 2, 5, 5,
        2, 2, 2, 2, 5, 5])</code></pre>
</div>
</div>
<div id="dbc60dd4" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb197" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb197-1">(preds.argmax(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> yb).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="131">
<pre data-code-line-numbers=""><code>tensor(5)</code></pre>
</div>
</div>
<div id="3410c1a6" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb199" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb199-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> accuracy(preds, yb): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> ((preds.argmax(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> yb).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>()) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> yb.shape[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span></code></pre></div></div>
</div>
<div id="68c4231b" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb200" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb200-1">accuracy(preds, yb)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="133">
<pre data-code-line-numbers=""><code>tensor(0.10)</code></pre>
</div>
</div>
<div id="9625bd12" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb202" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb202-1">test_close(accuracy(preds, yb), (preds.argmax(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> yb).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>().mean())</span></code></pre></div></div>
</div>
<div id="2343f894" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb203" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb203-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> report(loss, preds, yb): <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'Loss: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>loss<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">; Accuracy: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>accuracy(preds, yb)<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:.2f}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>)</span></code></pre></div></div>
</div>
<div id="8c7aea92" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb204" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb204-1">lr, epochs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">.5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span></span>
<span id="cb204-2">xb, yb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_x[:bs], trn_y[:bs]</span>
<span id="cb204-3">preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(xb)</span>
<span id="cb204-4">report(loss_func(preds, yb), preds, yb)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>Loss: 2.30; Accuracy: 0.10</code></pre>
</div>
</div>
<p>The training loop can now be assembled.</p>
<div id="60928cbc" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb206" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb206-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> epoch <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(epochs):</span>
<span id="cb206-2">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, n, bs):</span>
<span id="cb206-3">    s <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">slice</span>(i, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(n, bs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>i))</span>
<span id="cb206-4">    xb, yb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_x[s], trn_y[s]</span>
<span id="cb206-5">    preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(xb)</span>
<span id="cb206-6">    loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss_func(preds, yb)</span>
<span id="cb206-7">    loss.backward()</span>
<span id="cb206-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> torch.no_grad():</span>
<span id="cb206-9">      <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> l <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> model.layers:</span>
<span id="cb206-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">hasattr</span>(l, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'weight'</span>):</span>
<span id="cb206-11">          l.weight <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-=</span> l.weight.grad <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> lr</span>
<span id="cb206-12">          l.bias   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-=</span> l.bias.grad <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> lr</span>
<span id="cb206-13">          l.weight.grad.zero_()</span>
<span id="cb206-14">          l.bias  .grad.zero_()</span>
<span id="cb206-15">  report(loss, preds, yb)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>Loss: 1.01; Accuracy: 0.66
Loss: 0.45; Accuracy: 0.88
Loss: 0.37; Accuracy: 0.82</code></pre>
</div>
</div>
<p>Let’s take a closer look at how we slice: <code>s = slice(i, min(n, bs+i))</code>. We have to use <code>min</code> to prevent the slices from going out of bounds.</p>

<div class="no-row-height column-margin column-container"><div id="65c42255" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb208" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb208-1">?<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">slice</span></span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<div class="ansi-escaped-output">
<pre><span class="ansi-red-fg">Init signature:</span> slice<span class="ansi-blue-fg">(</span>self<span class="ansi-blue-fg">,</span> <span class="ansi-blue-fg">/</span><span class="ansi-blue-fg">,</span> <span class="ansi-blue-fg">*</span>args<span class="ansi-blue-fg">,</span> <span class="ansi-blue-fg">**</span>kwargs<span class="ansi-blue-fg">)</span>

<span class="ansi-red-fg">Docstring:</span>     

slice(stop)

slice(start, stop[, step])



Create a slice object.  This is used for extended slicing (e.g. a[0:10:2]).

<span class="ansi-red-fg">Type:</span>           type

<span class="ansi-red-fg">Subclasses:</span>     </pre>
</div>
</div>
</div></div><div id="8af95381" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb209" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb209-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, n, bs): <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">slice</span>(i, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(n, bs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>i)))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>slice(0, 50, None)
slice(50, 100, None)
slice(100, 150, None)
slice(150, 200, None)
slice(200, 250, None)
slice(250, 300, None)
slice(300, 350, None)
slice(350, 400, None)
slice(400, 450, None)
slice(450, 500, None)
slice(500, 550, None)
slice(550, 600, None)
slice(600, 650, None)
slice(650, 700, None)
slice(700, 750, None)
slice(750, 800, None)
slice(800, 850, None)
slice(850, 900, None)
slice(900, 950, None)
slice(950, 1000, None)</code></pre>
</div>
</div>
<p>Simply adding <code>bs</code> to <code>n</code> at the <code>end</code> parameter for <code>range</code> will not work.</p>
<div id="69ff69da" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb211" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb211-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, n<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>bs, bs): <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">slice</span>(i, bs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>i))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>slice(0, 50, None)
slice(50, 100, None)
slice(100, 150, None)
slice(150, 200, None)
slice(200, 250, None)
slice(250, 300, None)
slice(300, 350, None)
slice(350, 400, None)
slice(400, 450, None)
slice(450, 500, None)
slice(500, 550, None)
slice(550, 600, None)
slice(600, 650, None)
slice(650, 700, None)
slice(700, 750, None)
slice(750, 800, None)
slice(800, 850, None)
slice(850, 900, None)
slice(900, 950, None)
slice(950, 1000, None)
slice(1000, 1050, None)</code></pre>
</div>
</div>
</section>
<section id="parameters-optimizers" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="parameters-optimizers">Parameters &amp; Optimizers</h2>
<p>Currently, we update our weights by checking whether a layer in our network has a <code>weight</code> attribute.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb213" data-code-line-numbers="8,9,10,11,12,13,14" style="background: #f1f3f5;"><pre class="sourceCode py code-with-copy"><code class="sourceCode python"><span id="cb213-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> epoch <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(epochs):</span>
<span id="cb213-2">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, n, bs):</span>
<span id="cb213-3">    s <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">slice</span>(i, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(n, bs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>i))</span>
<span id="cb213-4">    xb, yb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_x[s], trn_y[s]</span>
<span id="cb213-5">    preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(xb)</span>
<span id="cb213-6">    loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss_func(preds, yb)</span>
<span id="cb213-7">    loss.backward()</span>
<span id="cb213-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> torch.no_grad(): </span>
<span id="cb213-9">      <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> l <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> model.layers: </span>
<span id="cb213-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">hasattr</span>(l, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'weight'</span>): </span>
<span id="cb213-11">          l.weight <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-=</span> l.weight.grad <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> lr </span>
<span id="cb213-12">          l.bias   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-=</span> l.bias.grad <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> lr </span>
<span id="cb213-13">          l.weight.grad.zero_() </span>
<span id="cb213-14">          l.bias  .grad.zero_() </span>
<span id="cb213-15">  report(loss, preds, yb)</span></code></pre></div></div>
<p>PyTorch actually keeps track which layers have weights. Let us explore.</p>
<p>Here, PyTorch knows that our model has a linear layer with 3 inputs and 4 outputs.</p>
<div id="518b3601" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb214" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb214-1">m1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Module()</span>
<span id="cb214-2">m1.foo <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Linear(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> m1</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="141">
<pre data-code-line-numbers=""><code>Module(
  (foo): Linear(in_features=3, out_features=4, bias=True)
)</code></pre>
</div>
</div>
<div id="b3c13250" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb216" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb216-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(m1.named_children())</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="142">
<pre data-code-line-numbers=""><code>[('foo', Linear(in_features=3, out_features=4, bias=True))]</code></pre>
</div>
</div>
<p>In a similar manner, we can access the layer’s parameters.</p>
<div id="5cb14579" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb218" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb218-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(m1.foo.parameters())</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="145">
<pre data-code-line-numbers=""><code>[Parameter containing:
 tensor([[-0.37,  0.20, -0.39],
         [-0.47,  0.00,  0.18],
         [ 0.51, -0.35,  0.36],
         [ 0.12,  0.10, -0.03]], requires_grad=True),
 Parameter containing:
 tensor([ 0.31, -0.42,  0.35,  0.16], requires_grad=True)]</code></pre>
</div>
</div>
<p>However, this approach will require us to loop through all layers to access all parameters. PyTorch instead provides a way to directly return the parameters of all layers.</p>
<div id="8b8dde08" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb220" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb220-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(m1.parameters())</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="146">
<pre data-code-line-numbers=""><code>[Parameter containing:
 tensor([[-0.37,  0.20, -0.39],
         [-0.47,  0.00,  0.18],
         [ 0.51, -0.35,  0.36],
         [ 0.12,  0.10, -0.03]], requires_grad=True),
 Parameter containing:
 tensor([ 0.31, -0.42,  0.35,  0.16], requires_grad=True)]</code></pre>
</div>
</div>
<div id="ecfd2651" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb222" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb222-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> MLP(nn.Module):</span>
<span id="cb222-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, n_inps, nh, n_outs):</span>
<span id="cb222-3">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">super</span>().<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>()</span>
<span id="cb222-4">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.l1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Linear(n_inps, nh)</span>
<span id="cb222-5">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.l2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Linear(nh, n_outs)</span>
<span id="cb222-6">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.relu <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.ReLU()</span>
<span id="cb222-7">  </span>
<span id="cb222-8">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> forward(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, x): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.l2(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.relu(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.l1(x)))</span></code></pre></div></div>
</div>
<div id="4026e7fd" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb223" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb223-1">n, m, nh, c</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="148">
<pre data-code-line-numbers=""><code>(1000, 784, 50, tensor(10))</code></pre>
</div>
</div>
<div id="0da68c6d" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb225" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb225-1">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> MLP(m, nh, c)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> model.l1</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="149">
<pre data-code-line-numbers=""><code>Linear(in_features=784, out_features=50, bias=True)</code></pre>
</div>
</div>
<div id="ace2a11e" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb227" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb227-1">model</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="150">
<pre data-code-line-numbers=""><code>MLP(
  (l1): Linear(in_features=784, out_features=50, bias=True)
  (l2): Linear(in_features=50, out_features=10, bias=True)
  (relu): ReLU()
)</code></pre>
</div>
</div>
<div id="81516481" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb229" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb229-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> name, l <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> model.named_children(): <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>name<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">: </span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>l<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>l1: Linear(in_features=784, out_features=50, bias=True)
l2: Linear(in_features=50, out_features=10, bias=True)
relu: ReLU()</code></pre>
</div>
</div>
<div id="0e1f3a5e" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb231" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb231-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> p <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> model.parameters(): <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(p.shape)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>torch.Size([50, 784])
torch.Size([50])
torch.Size([10, 50])
torch.Size([10])</code></pre>
</div>
</div>
<p>Since we can directly access the parameters, we do not need to check whether a certain parameter exists.</p>
<div id="fe89d5de" class="cell" data-source-line-numbers="9-12">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-151" data-source-line-numbers="9-12" data-code-line-numbers="9-12" style="background: #f1f3f5;"><pre class="sourceCode python code-annotation-code code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-151-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fit():</span>
<span id="annotated-cell-151-2">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> epoch <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(epochs):</span>
<span id="annotated-cell-151-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, n, bs):</span>
<span id="annotated-cell-151-4">      s <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">slice</span>(i, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(n, bs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>i))</span>
<span id="annotated-cell-151-5">      xb, yb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_x[s], trn_y[s]</span>
<span id="annotated-cell-151-6">      preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(xb)</span>
<span id="annotated-cell-151-7">      loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss_func(preds, yb)</span>
<span id="annotated-cell-151-8">      loss.backward()</span>
<span id="annotated-cell-151-9">      <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> torch.no_grad():</span>
<span id="annotated-cell-151-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> p <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> model.parameters(): p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-=</span> p.grad <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> lr</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-151" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-151-11" class="code-annotation-target">        model.zero_grad()</span>
<span id="annotated-cell-151-12">    report(loss, preds, yb)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-151" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-151" data-code-lines="11" data-code-annotation="1"><code>torch.zero_grad()</code> can also be called directly on the model itself.</span>
</dd>
</dl>
</div>
</div>
<div id="fd2ff6c7" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb233" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb233-1">fit()</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>Loss: 0.84; Accuracy: 0.74
Loss: 0.45; Accuracy: 0.88
Loss: 0.37; Accuracy: 0.84</code></pre>
</div>
</div>
<p>Let us implement this functionality–where the model itself knows what its layers and parameters are–ourselves.</p>
<p>To do so, we will need to define the <code>__setattr__</code> dunder method, where any submodules defined are registered as parameters of the model.</p>
<div id="6570cad7" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-153" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-annotation-code code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-153-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> MyModule:</span>
<span id="annotated-cell-153-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, n_inps, nh, n_outs):</span>
<span id="annotated-cell-153-3">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>._modules <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}</span>
<span id="annotated-cell-153-4">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.l1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Linear(n_inps, nh)</span>
<span id="annotated-cell-153-5">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.l2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Linear(nh, n_outs)</span>
<span id="annotated-cell-153-6">  </span>
<span id="annotated-cell-153-7">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__setattr__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, k, v):</span>
<span id="annotated-cell-153-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">not</span> k.startswith(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'_'</span>): <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>._modules[k] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> v</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-153" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-153-9" class="code-annotation-target">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">super</span>().<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__setattr__</span>(k, v)</span>
<span id="annotated-cell-153-10">  </span>
<span id="annotated-cell-153-11">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__repr__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span>_modules<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span></span>
<span id="annotated-cell-153-12"></span>
<span id="annotated-cell-153-13">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> parameters(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="annotated-cell-153-14">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> l <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>._modules.values(): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> l.parameters()</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-153" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-153" data-code-lines="9" data-code-annotation="1"><code>class MyModule</code> is actually <code>class MyModule(object)</code></span>
</dd>
</dl>
</div>
</div>
<div id="1eb9440f" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb235" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb235-1">mdl <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> MyModule(m, nh, c)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> mdl, model</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="157">
<pre data-code-line-numbers=""><code>({'l1': Linear(in_features=784, out_features=50, bias=True), 'l2': Linear(in_features=50, out_features=10, bias=True)},
 MLP(
   (l1): Linear(in_features=784, out_features=50, bias=True)
   (l2): Linear(in_features=50, out_features=10, bias=True)
   (relu): ReLU()
 ))</code></pre>
</div>
</div>
<div id="0a36c426" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb237" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb237-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> p <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> mdl.parameters(): <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(p.shape)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>torch.Size([50, 784])
torch.Size([50])
torch.Size([10, 50])
torch.Size([10])</code></pre>
</div>
</div>
<section id="registering-modules" class="level3 page-columns page-full">
<h3 class="anchored" data-anchor-id="registering-modules">Registering Modules</h3>
<p>To use our original approach, where a list of layers are specified, we can use the <code>add_module</code> method provided by PyTorch.</p>
<div id="05ba266a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb239" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb239-1">?nn.Module.add_module</span></code></pre></div></div>
</div>
<div id="6b310a72" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb240" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb240-1">layers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [nn.Linear(m, nh), nn.ReLU(), nn.Linear(nh, c)]</span></code></pre></div></div>
</div>
<div id="c08683d9" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-158" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-annotation-code code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-158-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> functools <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">reduce</span></span>
<span id="annotated-cell-158-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Model(nn.Module):</span>
<span id="annotated-cell-158-3">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, layers):</span>
<span id="annotated-cell-158-4">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">super</span>().<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>()</span>
<span id="annotated-cell-158-5">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.layers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> layers</span>
<span id="annotated-cell-158-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, l <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.layers): <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.add_module(<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f'layer_</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>, l)</span>
<span id="annotated-cell-158-7"></span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-158" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-158-8" class="code-annotation-target">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> forward(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, x): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">reduce</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> val, layer: layer(val), <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.layers, x)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-158" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-158" data-code-lines="8" data-code-annotation="1">In essence, <code>reduce</code> uses the output of the function as input to the same function in the next iteration.</span>
</dd>
</dl>
</div>
</div>

<div class="no-row-height column-margin column-container"><div id="d8242ae6" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb241" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb241-1">?<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">reduce</span></span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<div class="ansi-escaped-output">
<pre><span class="ansi-red-fg">Docstring:</span>

reduce(function, iterable[, initial]) -&gt; value



Apply a function of two arguments cumulatively to the items of a sequence

or iterable, from left to right, so as to reduce the iterable to a single

value.  For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates

((((1+2)+3)+4)+5).  If initial is present, it is placed before the items

of the iterable in the calculation, and serves as a default when the

iterable is empty.

<span class="ansi-red-fg">Type:</span>      builtin_function_or_method</pre>
</div>
</div>
</div></div><div id="542e5ebb" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb242" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb242-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">reduce</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> x,y: x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>y, [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>])</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="163">
<pre data-code-line-numbers=""><code>15</code></pre>
</div>
</div>
<div id="e06e4f69" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb244" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb244-1">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Model(layers)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> model</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="164">
<pre data-code-line-numbers=""><code>Model(
  (layer_0): Linear(in_features=784, out_features=50, bias=True)
  (layer_1): ReLU()
  (layer_2): Linear(in_features=50, out_features=10, bias=True)
)</code></pre>
</div>
</div>
<div id="dc6a00a7" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb246" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb246-1">model(xb).shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="165">
<pre data-code-line-numbers=""><code>torch.Size([50, 10])</code></pre>
</div>
</div>
<p>Alternatively, <code>nn.ModuleList</code> can do the registration for us.</p>

<div class="no-row-height column-margin column-container"><div id="3066a594" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb248" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb248-1">?nn.ModuleList</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<div class="ansi-escaped-output">
<pre><span class="ansi-red-fg">Init signature:</span>

nn<span class="ansi-blue-fg">.</span>ModuleList<span class="ansi-blue-fg">(</span>

    modules<span class="ansi-blue-fg">:</span> Optional<span class="ansi-blue-fg">[</span>Iterable<span class="ansi-blue-fg">[</span>torch<span class="ansi-blue-fg">.</span>nn<span class="ansi-blue-fg">.</span>modules<span class="ansi-blue-fg">.</span>module<span class="ansi-blue-fg">.</span>Module<span class="ansi-blue-fg">]</span><span class="ansi-blue-fg">]</span> <span class="ansi-blue-fg">=</span> <span class="ansi-green-fg">None</span><span class="ansi-blue-fg">,</span>

<span class="ansi-blue-fg">)</span> <span class="ansi-blue-fg">-&gt;</span> <span class="ansi-green-fg">None</span>

<span class="ansi-red-fg">Docstring:</span>     

Holds submodules in a list.



:class:`~torch.nn.ModuleList` can be indexed like a regular Python list, but

modules it contains are properly registered, and will be visible by all

:class:`~torch.nn.Module` methods.



Args:

    modules (iterable, optional): an iterable of modules to add



Example::



    class MyModule(nn.Module):

        def __init__(self):

            super().__init__()

            self.linears = nn.ModuleList([nn.Linear(10, 10) for i in range(10)])



        def forward(self, x):

            # ModuleList can act as an iterable, or be indexed using ints

            for i, l in enumerate(self.linears):

                x = self.linears[i // 2](x) + l(x)

            return x

<span class="ansi-red-fg">Init docstring:</span> Initializes internal Module state, shared by both nn.Module and ScriptModule.

<span class="ansi-red-fg">File:</span>           ~/mambaforge/envs/default/lib/python3.10/site-packages/torch/nn/modules/container.py

<span class="ansi-red-fg">Type:</span>           type

<span class="ansi-red-fg">Subclasses:</span>     ParametrizationList</pre>
</div>
</div>
</div></div><div id="c340ed89" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb249" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb249-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> SequentialModel(nn.Module):</span>
<span id="cb249-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, layers):</span>
<span id="cb249-3">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">super</span>().<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>()</span>
<span id="cb249-4">    <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.layers <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.ModuleList(layers)</span>
<span id="cb249-5">  </span>
<span id="cb249-6">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> forward(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, x): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">reduce</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">lambda</span> x, layer: layer(x), <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.layers, x)</span></code></pre></div></div>
</div>
<div id="b0f5e7df" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb250" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb250-1">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> SequentialModel(layers)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> model</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="168">
<pre data-code-line-numbers=""><code>SequentialModel(
  (layers): ModuleList(
    (0): Linear(in_features=784, out_features=50, bias=True)
    (1): ReLU()
    (2): Linear(in_features=50, out_features=10, bias=True)
  )
)</code></pre>
</div>
</div>
<div id="a8472f9b" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb252" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb252-1">fit()</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>Loss: 0.93; Accuracy: 0.78
Loss: 0.52; Accuracy: 0.86
Loss: 0.38; Accuracy: 0.86</code></pre>
</div>
</div>
<div id="46100a44" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb254" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb254-1">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Sequential(nn.Linear(m, nh), nn.ReLU(), nn.Linear(nh, c))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> model</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="170">
<pre data-code-line-numbers=""><code>Sequential(
  (0): Linear(in_features=784, out_features=50, bias=True)
  (1): ReLU()
  (2): Linear(in_features=50, out_features=10, bias=True)
)</code></pre>
</div>
</div>
<div id="85cf8df7" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb256" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb256-1">fit()</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>Loss: 0.88; Accuracy: 0.74
Loss: 0.48; Accuracy: 0.86
Loss: 0.39; Accuracy: 0.88</code></pre>
</div>
</div>
</section>
<section id="optimizer" class="level3">
<h3 class="anchored" data-anchor-id="optimizer">Optimizer</h3>
<p>Optimizer is simply the name given to the algorithm that updates the weights.</p>
<div id="7be70aed" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb258" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb258-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Optimizer:</span>
<span id="cb258-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, params, lr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>): <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.params,<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.lr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(params), lr</span>
<span id="cb258-3"></span>
<span id="cb258-4">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> step(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb258-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> torch.no_grad():</span>
<span id="cb258-6">      <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> p <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.params: p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-=</span> p.grad <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.lr</span>
<span id="cb258-7">  </span>
<span id="cb258-8">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> zero_grad(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb258-9">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> p <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.params: p.grad.data.zero_()</span></code></pre></div></div>
</div>
<div id="1a1e8250" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb259" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb259-1">model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Sequential(nn.Linear(m, nh), nn.ReLU(), nn.Linear(nh, c))</span>
<span id="cb259-2">opt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Optimizer(model.parameters())</span></code></pre></div></div>
</div>
<p>The weight update step can now be cleaned up by using <code>opt.step()</code> and <code>opt.zero_grad()</code> instead.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb260" data-code-line-numbers="9,10,11" style="background: #f1f3f5;"><pre class="sourceCode py code-with-copy"><code class="sourceCode python"><span id="cb260-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fit():</span>
<span id="cb260-2">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> epoch <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(epochs):</span>
<span id="cb260-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, n, bs):</span>
<span id="cb260-4">      s <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">slice</span>(i, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(n, i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>bs))</span>
<span id="cb260-5">      xb, yb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_x[s], trn_y[s]</span>
<span id="cb260-6">      preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(xb)</span>
<span id="cb260-7">      loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss_func(preds, yb)</span>
<span id="cb260-8">      loss.backward()</span>
<span id="cb260-9">      <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> torch.no_grad(): </span>
<span id="cb260-10">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> p <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> model.parameters(): p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-=</span> p.grad <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> lr </span>
<span id="cb260-11">        model.zero_grad() </span>
<span id="cb260-12">    report(loss, preds, yb)</span></code></pre></div></div>
<div id="ada0ed2e" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb261" data-source-line-numbers="nil" data-code-line-numbers="9,10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb261-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fit():</span>
<span id="cb261-2">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> epoch <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(epochs):</span>
<span id="cb261-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, n, bs):</span>
<span id="cb261-4">      s <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">slice</span>(i, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(n, i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>bs))</span>
<span id="cb261-5">      xb, yb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_x[s], trn_y[s]</span>
<span id="cb261-6">      preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(xb)</span>
<span id="cb261-7">      loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss_func(preds, yb)</span>
<span id="cb261-8">      loss.backward()</span>
<span id="cb261-9">      opt.step() </span>
<span id="cb261-10">      opt.zero_grad() </span>
<span id="cb261-11">    report(loss, preds, yb)</span></code></pre></div></div>
</div>
<div id="cc868546" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb262" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb262-1">fit()</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>Loss: 0.89; Accuracy: 0.74
Loss: 0.51; Accuracy: 0.88
Loss: 0.41; Accuracy: 0.86</code></pre>
</div>
</div>
<div id="439c5a6c" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb264" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb264-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> torch <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> optim</span>
<span id="cb264-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_model():</span>
<span id="cb264-3">  model <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> nn.Sequential(nn.Linear(m, nh), nn.ReLU(), nn.Linear(nh, c))</span>
<span id="cb264-4">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> model, optim.SGD(model.parameters(), lr<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>lr)</span></code></pre></div></div>
</div>
<div id="5d624e5a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb265" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb265-1">model, opt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_model()</span>
<span id="cb265-2">loss_func(model(xb), yb)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="177">
<pre data-code-line-numbers=""><code>tensor(2.32, grad_fn=&lt;NllLossBackward0&gt;)</code></pre>
</div>
</div>
<div id="cbd03baf" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb267" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb267-1">fit()</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>Loss: 0.82; Accuracy: 0.78
Loss: 0.42; Accuracy: 0.90
Loss: 0.35; Accuracy: 0.86</code></pre>
</div>
</div>
</section>
</section>
<section id="dataset-and-dataloader" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="dataset-and-dataloader">Dataset and Dataloader</h2>
<p>I sometimes get confuzzled between the two terms, with regard to what each component actually does. The best way to think about these terms is that a dataset simply stores data in a massive warehouse, while a dataloader takes data from the dataset and tosses them into crates known as batches.</p>
<p>As it currently is, we iterate through our dataset by obtaining a slice object, and then slicing out some data to form a batch.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb269" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode py code-with-copy"><code class="sourceCode python"><span id="cb269-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, n, bs):</span>
<span id="cb269-2">  s <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">slice</span>(i, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(n, bs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>i))</span>
<span id="cb269-3">  xb, yb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_x[s], trn_y[s]</span></code></pre></div></div>
<p>We will now simplify how we approach this logic.</p>
<section id="dataset" class="level3">
<h3 class="anchored" data-anchor-id="dataset">Dataset</h3>
<p>The first point of simplification is to create a single dataset that will return both a sample and its associated target, from a single index. This will prevent us from having to index into two separate tensors.</p>
<div id="54c9d28c" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb270" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb270-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Dataset():</span>
<span id="cb270-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, x, y): <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.x, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> x, y</span>
<span id="cb270-3">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__len__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.x)</span>
<span id="cb270-4">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__getitem__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, i): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.x[i], <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.y[i]</span></code></pre></div></div>
</div>
<div id="6c9f9b92" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb271" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb271-1">trn_ds, vld_ds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Dataset(trn_x, trn_y), Dataset(vld_x, vld_y)</span>
<span id="cb271-2"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(trn_ds) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(trn_x)</span>
<span id="cb271-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(vld_ds) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(vld_x)</span></code></pre></div></div>
</div>
<div id="5a5b3e07" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb272" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb272-1">xb, yb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_ds[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>]</span>
<span id="cb272-2"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> xb.shape <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">28</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">28</span>)</span>
<span id="cb272-3"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">assert</span> yb.shape <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>,)</span>
<span id="cb272-4">xb, yb</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="181">
<pre data-code-line-numbers=""><code>(tensor([[0., 0., 0.,  ..., 0., 0., 0.],
         [0., 0., 0.,  ..., 0., 0., 0.],
         [0., 0., 0.,  ..., 0., 0., 0.],
         [0., 0., 0.,  ..., 0., 0., 0.],
         [0., 0., 0.,  ..., 0., 0., 0.]]),
 tensor([5, 0, 4, 1, 9]))</code></pre>
</div>
</div>
<div id="bf795af6" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb274" data-source-line-numbers="nil" data-code-line-numbers="4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb274-1">model, opt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_model()</span>
<span id="cb274-2"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> epoch <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(epochs):</span>
<span id="cb274-3">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, n, bs):</span>
<span id="cb274-4">    xb, yb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_ds[i:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(n, bs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>i)] </span>
<span id="cb274-5">    preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(xb)</span>
<span id="cb274-6">    loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss_func(preds, yb)</span>
<span id="cb274-7">    loss.backward()</span>
<span id="cb274-8">    opt.step()</span>
<span id="cb274-9">    opt.zero_grad()</span>
<span id="cb274-10">  report(loss, preds, yb)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>Loss: 1.19; Accuracy: 0.70
Loss: 0.50; Accuracy: 0.88
Loss: 0.34; Accuracy: 0.88</code></pre>
</div>
</div>
</section>
<section id="dataloader" class="level3">
<h3 class="anchored" data-anchor-id="dataloader">DataLoader</h3>
<p>Let us now abstract away how the data from our datasets is loaded, by putting the logic that fetches data from the dataset…</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb276" data-code-line-numbers="2" style="background: #f1f3f5;"><pre class="sourceCode py code-with-copy"><code class="sourceCode python"><span id="cb276-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, n, bs):</span>
<span id="cb276-2">  xb, yb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_ds[i:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(n,i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>bs)] </span>
<span id="cb276-3">  ...</span></code></pre></div></div>
<p>…into a class that we can call a dataloader.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb277" data-code-line-numbers="1" style="background: #f1f3f5;"><pre class="sourceCode py code-with-copy"><code class="sourceCode python"><span id="cb277-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> xb, yb <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> train_dl: </span>
<span id="cb277-2">  ...</span></code></pre></div></div>
<div id="f7614b5e" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb278" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb278-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> DataLoader():</span>
<span id="cb278-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, ds, bs): <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.ds,<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.bs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ds,bs</span>
<span id="cb278-3">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__iter__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb278-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.ds), <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.bs): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.ds[i:<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.ds), i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.bs)]</span></code></pre></div></div>
</div>
<div id="8c2fdc2a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb279" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb279-1">trn_dl, vld_dl <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataLoader(trn_ds, bs), DataLoader(vld_ds, bs)</span></code></pre></div></div>
</div>
<div id="69f174bf" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb280" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb280-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(vld_dl))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="185">
<pre data-code-line-numbers=""><code>(tensor([[0., 0., 0.,  ..., 0., 0., 0.],
         [0., 0., 0.,  ..., 0., 0., 0.],
         [0., 0., 0.,  ..., 0., 0., 0.],
         ...,
         [0., 0., 0.,  ..., 0., 0., 0.],
         [0., 0., 0.,  ..., 0., 0., 0.],
         [0., 0., 0.,  ..., 0., 0., 0.]]),
 tensor([3, 8, 6, 9, 6, 4, 5, 3, 8, 4, 5, 2, 3, 8, 4, 8, 1, 5, 0, 5, 9, 7, 4, 1, 0, 3, 0, 6, 2, 9, 9, 4, 1, 3, 6, 8, 0, 7, 7, 6, 8, 9, 0, 3,
         8, 3, 7, 7, 8, 4]))</code></pre>
</div>
</div>
<div id="2b40a65f" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb282" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb282-1">xb, yb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(vld_dl))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> xb.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="186">
<pre data-code-line-numbers=""><code>torch.Size([50, 784])</code></pre>
</div>
</div>
<div id="fbefedde" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb284" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb284-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> matplotlib.pyplot <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> plt</span>
<span id="cb284-2">plt.imshow(xb[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].view(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">28</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">28</span>))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> yb[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="187">
<pre data-code-line-numbers=""><code>tensor(3)</code></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://forbo7.github.io/forblog/posts/20_models_from_scratch_files/figure-html/cell-188-output-2.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="f3940556" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb286" data-source-line-numbers="nil" data-code-line-numbers="3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb286-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fit():</span>
<span id="cb286-2">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> epoch <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(epochs):</span>
<span id="cb286-3">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> xb, yb <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> trn_dl: </span>
<span id="cb286-4">      preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(xb)</span>
<span id="cb286-5">      loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss_func(preds, yb)</span>
<span id="cb286-6">      loss.backward()</span>
<span id="cb286-7">      opt.step()</span>
<span id="cb286-8">      opt.zero_grad()</span>
<span id="cb286-9">    report(loss, preds, yb)</span></code></pre></div></div>
</div>
<div id="75946953" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb287" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb287-1">model, opt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_model()</span>
<span id="cb287-2">fit()</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>Loss: 0.79; Accuracy: 0.82
Loss: 0.49; Accuracy: 0.84
Loss: 0.30; Accuracy: 0.88</code></pre>
</div>
</div>
<p>And just like that, we have abstracted our loading logic from three lines…</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb289" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode py code-with-copy"><code class="sourceCode python"><span id="cb289-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, n, bs):</span>
<span id="cb289-2">  s <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">slice</span>(i, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(n, bs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>i))</span>
<span id="cb289-3">  xb, yb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> trn_x[s], trn_y[s]</span>
<span id="cb289-4">  ...</span></code></pre></div></div>
<p>…to a much more readable single line.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb290" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode py code-with-copy"><code class="sourceCode python"><span id="cb290-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> xb, yb <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> trn_dl:</span>
<span id="cb290-2">  ...</span></code></pre></div></div>
</section>
<section id="random-sampling" class="level3 page-columns page-full">
<h3 class="anchored" data-anchor-id="random-sampling">Random Sampling</h3>
<p>Sampling is the method by which the dataloader selects indices from the dataset to load. Sampling from the training set should be random (due to the nature of our data), but not for the validation set.</p>
<p>Therefore, we will need to create an additional class for the our dataloader; a component that tells the dataloader from which indices to load data from the dataset.</p>
<div id="dcb92a5b" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb291" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb291-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> random</span>
<span id="cb291-2">?random.shuffle</span></code></pre></div></div>
</div>
<div id="b70e58fd" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb292" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb292-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Sampler():</span>
<span id="cb292-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, ds, shuffle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>): <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.n,<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.shuffle <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(ds),shuffle</span>
<span id="cb292-3">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__iter__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb292-4">    res <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.n))</span>
<span id="cb292-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.shuffle: random.shuffle(res)</span>
<span id="cb292-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(res)</span></code></pre></div></div>
</div>
<div id="59c31a81" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb293" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb293-1">ss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Sampler(trn_ds)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> ss</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="192">
<pre data-code-line-numbers=""><code>&lt;__main__.Sampler at 0x150dddd80&gt;</code></pre>
</div>
</div>

<div class="no-row-height column-margin column-container"><div id="14a6d765" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb295" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb295-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(ss))</span>
<span id="cb295-2"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">except</span>: <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">pass</span></span></code></pre></div></div>
</div><div class="">
<p>This does not work because <code>__iter__</code> is not being called. <code>__iter__</code> only gets called when we wrap the class with <code>iter()</code>.</p>
</div><div id="8fe59206" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb296" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb296-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">try</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(ss)))</span>
<span id="cb296-2"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">except</span>: <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">pass</span></span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>0</code></pre>
</div>
</div></div>

<div id="d7a8a588" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb298" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb298-1">it <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(ss)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> it</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="195">
<pre data-code-line-numbers=""><code>&lt;list_iterator at 0x150996fe0&gt;</code></pre>
</div>
</div>
<div id="ba01f4d1" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb300" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb300-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> o <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>): <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(it))</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>0
1
2
3
4</code></pre>
</div>
</div>
<p>The <code>Sampler</code> currently returns a single index in each iteration. We need to change that so a number of indices (equal to our batch size) is returned in each iteration. We can do this through a fancy slicing function known as <code>islice</code>.</p>
<div id="7a7c52c1" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb302" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb302-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> itertools <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> islice</span>
<span id="cb302-2">?islice</span></code></pre></div></div>
</div>
<p><code>iter</code> returns a single element from an iterable at a time. <code>islice</code> is a type of iterator that returns <img src="https://latex.codecogs.com/png.latex?x"> elements from an iterable at a time. It is an, erm, iterative slice.</p>
<div id="8eac61f6" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb303" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb303-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(islice(ss, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="198">
<pre data-code-line-numbers=""><code>[0, 1, 2, 3, 4]</code></pre>
</div>
</div>
<p>Let’s define an additional class that takes a sampler, and assembles its output into batches.</p>
<div id="a58331af" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-202" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-annotation-code code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-202-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> BatchSampler:</span>
<span id="annotated-cell-202-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, sampler, bs, drop_last<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>): store_attr()</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-202" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-202-3" class="code-annotation-target">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__iter__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> chunked(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.sampler), <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.bs, drop_last<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.drop_last)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-202" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-202" data-code-lines="3" data-code-annotation="1"><code>fastcore</code>’s <code>chunked</code> function has the exact same functionality as <code>islice</code>, but with some extra quality of life features. This includes being able to specify how many chunks, or slices, we want back (rather than the number of elements in a chunk), as well as being able to specify whether we would like to drop, or keep, chunks that are smaller than our specified chunk size. This latter option is what we will use–it will abstract away the <code>min</code> check we use in our <code>DataLoader</code> (<code>self.ds[i:min(len(self.ds), i+self.bs)]</code>).</span>
</dd>
</dl>
</div>
</div>

<div class="no-row-height column-margin column-container"><div id="f126b243" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb305" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb305-1">??chunked</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<div class="ansi-escaped-output">
<pre><span class="ansi-red-fg">Signature:</span> chunked<span class="ansi-blue-fg">(</span>it<span class="ansi-blue-fg">,</span> chunk_sz<span class="ansi-blue-fg">=</span><span class="ansi-green-fg">None</span><span class="ansi-blue-fg">,</span> drop_last<span class="ansi-blue-fg">=</span><span class="ansi-green-fg">False</span><span class="ansi-blue-fg">,</span> n_chunks<span class="ansi-blue-fg">=</span><span class="ansi-green-fg">None</span><span class="ansi-blue-fg">)</span>

<span class="ansi-red-fg">Source:</span>   

<span class="ansi-green-fg">def</span> chunked<span class="ansi-blue-fg">(</span>it<span class="ansi-blue-fg">,</span> chunk_sz<span class="ansi-blue-fg">=</span><span class="ansi-green-fg">None</span><span class="ansi-blue-fg">,</span> drop_last<span class="ansi-blue-fg">=</span><span class="ansi-green-fg">False</span><span class="ansi-blue-fg">,</span> n_chunks<span class="ansi-blue-fg">=</span><span class="ansi-green-fg">None</span><span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">:</span>

    <span class="ansi-blue-fg">"Return batches from iterator `it` of size `chunk_sz` (or return `n_chunks` total)"</span>

    <span class="ansi-green-fg">assert</span> bool<span class="ansi-blue-fg">(</span>chunk_sz<span class="ansi-blue-fg">)</span> <span class="ansi-blue-fg">^</span> bool<span class="ansi-blue-fg">(</span>n_chunks<span class="ansi-blue-fg">)</span>

    <span class="ansi-green-fg">if</span> n_chunks<span class="ansi-blue-fg">:</span> chunk_sz <span class="ansi-blue-fg">=</span> max<span class="ansi-blue-fg">(</span>math<span class="ansi-blue-fg">.</span>ceil<span class="ansi-blue-fg">(</span>len<span class="ansi-blue-fg">(</span>it<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">/</span>n_chunks<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">,</span> <span class="ansi-cyan-fg">1</span><span class="ansi-blue-fg">)</span>

    <span class="ansi-green-fg">if</span> <span class="ansi-green-fg">not</span> isinstance<span class="ansi-blue-fg">(</span>it<span class="ansi-blue-fg">,</span> Iterator<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">:</span> it <span class="ansi-blue-fg">=</span> iter<span class="ansi-blue-fg">(</span>it<span class="ansi-blue-fg">)</span>

    <span class="ansi-green-fg">while</span> <span class="ansi-green-fg">True</span><span class="ansi-blue-fg">:</span>

        res <span class="ansi-blue-fg">=</span> list<span class="ansi-blue-fg">(</span>itertools<span class="ansi-blue-fg">.</span>islice<span class="ansi-blue-fg">(</span>it<span class="ansi-blue-fg">,</span> chunk_sz<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">)</span>

        <span class="ansi-green-fg">if</span> res <span class="ansi-green-fg">and</span> <span class="ansi-blue-fg">(</span>len<span class="ansi-blue-fg">(</span>res<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">==</span>chunk_sz <span class="ansi-green-fg">or</span> <span class="ansi-green-fg">not</span> drop_last<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">:</span> <span class="ansi-green-fg">yield</span> res

        <span class="ansi-green-fg">if</span> len<span class="ansi-blue-fg">(</span>res<span class="ansi-blue-fg">)</span><span class="ansi-blue-fg">&lt;</span>chunk_sz<span class="ansi-blue-fg">:</span> <span class="ansi-green-fg">return</span>

<span class="ansi-red-fg">File:</span>      ~/mambaforge/envs/default/lib/python3.10/site-packages/fastcore/basics.py

<span class="ansi-red-fg">Type:</span>      function</pre>
</div>
</div>
</div></div><div id="c4b8b065" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb306" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb306-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(islice(ss, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="201">
<pre data-code-line-numbers=""><code>[0, 1, 2, 3, 4]</code></pre>
</div>
</div>
<div id="404961d9" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb308" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb308-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(chunked(ss, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>))[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="202">
<pre data-code-line-numbers=""><code>[[0, 1, 2, 3, 4],
 [5, 6, 7, 8, 9],
 [10, 11, 12, 13, 14],
 [15, 16, 17, 18, 19],
 [20, 21, 22, 23, 24]]</code></pre>
</div>
</div>
<div id="42f10cfc" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb310" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb310-1">batches <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> BatchSampler(ss, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)</span>
<span id="cb310-2"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(islice(batches, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="203">
<pre data-code-line-numbers=""><code>[[0, 1, 2, 3],
 [4, 5, 6, 7],
 [8, 9, 10, 11],
 [12, 13, 14, 15],
 [16, 17, 18, 19]]</code></pre>
</div>
</div>
</section>
<section id="collation" class="level3">
<h3 class="anchored" data-anchor-id="collation">Collation</h3>
<p>There is one last piece of the puzzle left. Each sample in our <code>Dataset</code> also stores its associated target. We need to split these apart when dataloading. In other words, we need to split the data and target in each sample into their own batches; into an <code>x</code> batch and a <code>y</code> batch.</p>
<div id="fa800f63" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb312" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb312-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> collate(b):</span>
<span id="cb312-2">  xs, ys <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>b)</span>
<span id="cb312-3">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> torch.stack(xs), torch.stack(ys)</span></code></pre></div></div>
</div>
<div id="9b0c8e44" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb313" data-source-line-numbers="nil" data-code-line-numbers="3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb313-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> DataLoader():</span>
<span id="cb313-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, ds, batches, collate_fn<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>collate): store_attr()</span>
<span id="cb313-3">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__iter__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> (<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.collate_fn(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.ds[i] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> b) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> b <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.batches) </span></code></pre></div></div>
</div>
<p>Let’s breakdown the latter line and explore what it does, piece by piece.</p>
<div id="64cb5476" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb314" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb314-1">trn_samp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> BatchSampler(Sampler(trn_ds, shuffle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>), bs)</span>
<span id="cb314-2">vld_samp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> BatchSampler(Sampler(vld_ds, shuffle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>), bs)</span></code></pre></div></div>
</div>
<p><code>for b in self.batches</code>, we loop through each batch.</p>
<div id="f0eab102" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb315" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb315-1">b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(vld_samp))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> b[:<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span>]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="207">
<pre data-code-line-numbers=""><code>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]</code></pre>
</div>
</div>
<p><code>self.ds[i] for i in b</code>; using the indices in each batch, we access the respective samples in the dataset.</p>
<div id="0a4d4efa" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb317" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb317-1">p <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [vld_ds[i] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> b]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(p)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="208">
<pre data-code-line-numbers=""><code>50</code></pre>
</div>
</div>
<p>As can be seen below, <code>p</code> also stores the target.</p>
<div id="6f2df134" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb319" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb319-1">p[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span></code></pre></div></div>
</div>
<p>Then we simply run the collate function.</p>
<div id="adcdd69a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb320" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb320-1">xs, ys <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">zip</span>(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span>p)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> ys</span></code></pre></div></div>
</div>
<p>And there we have our collated <code>x</code> and <code>y</code> batches!</p>
<div id="4959d6e8" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb321" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb321-1">torch.stack(ys)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="211">
<pre data-code-line-numbers=""><code>tensor([3, 8, 6, 9, 6, 4, 5, 3, 8, 4, 5, 2, 3, 8, 4, 8, 1, 5, 0, 5, 9, 7, 4, 1, 0, 3, 0, 6, 2, 9, 9, 4, 1, 3, 6, 8, 0, 7, 7, 6, 8, 9, 0, 3,
        8, 3, 7, 7, 8, 4])</code></pre>
</div>
</div>
<div id="10544016" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb323" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb323-1">trn_samp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> BatchSampler(Sampler(trn_ds, shuffle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>), bs)</span>
<span id="cb323-2">vld_samp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> BatchSampler(Sampler(vld_ds, shuffle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>), bs)</span></code></pre></div></div>
</div>
<div id="169a301f" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb324" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb324-1">trn_dl <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataLoader(trn_ds, batches<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>trn_samp)</span>
<span id="cb324-2">vld_dl <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataLoader(vld_ds, batches<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>vld_samp)</span></code></pre></div></div>
</div>
<div id="dd134147" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb325" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb325-1">xb, yb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(vld_dl))</span>
<span id="cb325-2">plt.imshow(xb[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>].view(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">28</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">28</span>))</span>
<span id="cb325-3">yb[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="214">
<pre data-code-line-numbers=""><code>tensor(3)</code></pre>
</div>
<div class="cell-output cell-output-display">
<div>
<figure class="figure">
<p><img src="https://forbo7.github.io/forblog/posts/20_models_from_scratch_files/figure-html/cell-215-output-2.png" class="img-fluid figure-img"></p>
</figure>
</div>
</div>
</div>
<div id="5c94032d" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb327" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb327-1">xb.shape, yb.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="215">
<pre data-code-line-numbers=""><code>(torch.Size([50, 784]), torch.Size([50]))</code></pre>
</div>
</div>
<div id="564c3dfb" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb329" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb329-1">model, opt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_model()</span>
<span id="cb329-2">fit()</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>Loss: 1.03; Accuracy: 0.74
Loss: 0.46; Accuracy: 0.82
Loss: 0.30; Accuracy: 0.90</code></pre>
</div>
</div>
<p>We do not need to update the <code>fit()</code> function, as its logic remains the same despite our changes to the dataloader.</p>
<div id="b99b7269" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb331" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb331-1">??fit</span></code></pre></div></div>
</div>
</section>
<section id="multiprocessing-dataloader" class="level3">
<h3 class="anchored" data-anchor-id="multiprocessing-dataloader">Multiprocessing DataLoader</h3>
<p>We can speed up how quickly data is loaded by using multiple CPU cores.</p>
<div id="ece6c6f3" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb332" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb332-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%%</span>timeit</span>
<span id="cb332-2">it <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(trn_dl)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>227 ns ± 1.45 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)</code></pre>
</div>
</div>
<div id="bf7d20e8" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb334" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb334-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> torch.multiprocessing <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> mp</span>
<span id="cb334-2"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> DataLoader():</span>
<span id="cb334-3">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, ds, batches, n_workers<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, collate_fun<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>collate): store_attr()</span>
<span id="cb334-4">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__iter__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>):</span>
<span id="cb334-5">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> mp.Pool(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.n_workers) <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> ex: <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">yield</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">from</span> ex.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.ds.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__getitem__</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.batches))</span></code></pre></div></div>
</div>
<div id="9ef3d59a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb335" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb335-1">trn_dl <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataLoader(trn_ds, batches<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>trn_samp, n_workers<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)</span></code></pre></div></div>
</div>
<div id="dd6e2a81" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb336" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb336-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%%</span>timeit</span>
<span id="cb336-2">it <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(trn_dl)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>197 ns ± 0.557 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)</code></pre>
</div>
</div>
<p>Let’s break down how exactly our <code>__iter__</code> method works.</p>
<p>We slice batches by specifying a list of indices.</p>
<div id="447a5605" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb338" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb338-1">trn_ds[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="222">
<pre data-code-line-numbers=""><code>(tensor([[0., 0., 0.,  ..., 0., 0., 0.],
         [0., 0., 0.,  ..., 0., 0., 0.],
         [0., 0., 0.,  ..., 0., 0., 0.],
         [0., 0., 0.,  ..., 0., 0., 0.]]),
 tensor([1, 1, 1, 0]))</code></pre>
</div>
</div>
<p>Behind the scenes, the square bracket notation calls the <code>__getitem__</code> dunder method.</p>
<div id="3fac9268" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb340" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb340-1">??trn_ds.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__getitem__</span></span></code></pre></div></div>
</div>
<p>In fact, we can index directly using <code>__getitem__</code>.</p>
<div id="936f1dae" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb341" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb341-1">trn_ds.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__getitem__</span>([<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="224">
<pre data-code-line-numbers=""><code>(tensor([[0., 0., 0.,  ..., 0., 0., 0.],
         [0., 0., 0.,  ..., 0., 0., 0.],
         [0., 0., 0.,  ..., 0., 0., 0.],
         [0., 0., 0.,  ..., 0., 0., 0.]]),
 tensor([1, 1, 1, 0]))</code></pre>
</div>
</div>
<p>Therefore, by dividing our batches into smaller sets, we can take advantage of the <code>__getitem__</code> dunder method to allow each CPU core to handle a separate set of items.</p>
<p>So we can divide our batches into smaller sets that each CPU core can manage.</p>
<div id="d1883ae5" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb343" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb343-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(trn_ds.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__getitem__</span>, ([<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>], [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]))))</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="225">
<pre data-code-line-numbers=""><code>2</code></pre>
</div>
</div>
<div id="3bead6e1" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb345" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb345-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> o <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">map</span>(trn_ds.<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__getitem__</span>, ([<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>], [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])): <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(o)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>(tensor([[0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.]]), tensor([1, 1]))
(tensor([[0., 0., 0.,  ..., 0., 0., 0.],
        [0., 0., 0.,  ..., 0., 0., 0.]]), tensor([1, 0]))</code></pre>
</div>
</div>
</section>
<section id="sampling-in-pytorch" class="level3">
<h3 class="anchored" data-anchor-id="sampling-in-pytorch">Sampling in PyTorch</h3>
<div id="3fed08c1" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb347" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb347-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> torch.utils.data <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> DataLoader, SequentialSampler, RandomSampler, BatchSampler</span>
<span id="cb347-2">?BatchSampler</span></code></pre></div></div>
</div>
<p>PyTorch provides a wrapper which assembles the indices, sampled by our desired sampler, into batches.</p>
<div id="6e512e31" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb348" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb348-1">?RandomSampler</span></code></pre></div></div>
</div>
<div id="3ff495f4" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb349" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb349-1">trn_samp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> BatchSampler(    RandomSampler(trn_ds), bs, drop_last<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb349-2">vld_samp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> BatchSampler(SequentialSampler(vld_ds), bs, drop_last<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span></code></pre></div></div>
</div>
<p>To construct a dataloader with PyTorch, we have to provide the dataset and a sampler.</p>
<div id="f8fc0596" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb350" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb350-1">?DataLoader</span></code></pre></div></div>
</div>
<div id="b44d4548" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb351" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb351-1">trn_dl <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataLoader(trn_ds, batch_sampler<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>trn_samp, collate_fn<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>collate)</span>
<span id="cb351-2">vld_dl <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataLoader(vld_dl, batch_sampler<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>vld_samp, collate_fn<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>collate)</span></code></pre></div></div>
</div>
<div id="9849898c" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb352" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb352-1">model, opt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_model()</span>
<span id="cb352-2">fit()</span>
<span id="cb352-3">loss_func(model(xb), yb), accuracy(model(xb), yb)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>Loss: 1.05; Accuracy: 0.64
Loss: 0.69; Accuracy: 0.72
Loss: 0.55; Accuracy: 0.84</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="232">
<pre data-code-line-numbers=""><code>(tensor(1.02, grad_fn=&lt;NllLossBackward0&gt;), tensor(0.66))</code></pre>
</div>
</div>
<p>Instead of separately wrapping the <code>RandomSampler</code> and <code>SequentialSampler</code> classes, we can let the <code>DataLoader</code> class do this for us.</p>
<div id="496923bb" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb355" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb355-1">trn_dl <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataLoader(trn_ds, bs, sampler<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>    RandomSampler(trn_ds), collate_fn<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>collate)</span>
<span id="cb355-2">vld_dl <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataLoader(vld_ds, bs, sampler<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>SequentialSampler(trn_ds), collate_fn<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>collate)</span></code></pre></div></div>
</div>
<p>In fact, we don’t even need to specify the sampler. All we have to do is toggle and set some parameters.</p>
<div id="c75859cd" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb356" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb356-1">trn_dl <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataLoader(trn_ds, bs, shuffle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, drop_last<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, num_workers<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb356-2">vld_dl <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataLoader(vld_ds, bs, shuffle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>, num_workers<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span></code></pre></div></div>
</div>
<div id="db037326" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb357" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb357-1">model, opt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_model()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> fit()</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>Loss: 0.80; Accuracy: 0.80
Loss: 0.27; Accuracy: 0.94
Loss: 0.40; Accuracy: 0.88</code></pre>
</div>
</div>
<div id="852bc6d9" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb359" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb359-1">loss_func(model(xb), yb), accuracy(model(xb), yb)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="236">
<pre data-code-line-numbers=""><code>(tensor(0.84, grad_fn=&lt;NllLossBackward0&gt;), tensor(0.68))</code></pre>
</div>
</div>
<p>As our dataset already knows how to sample a batch of indices all at once, we can actually skip the <code>batch_sampler</code> and <code>collate_fn</code> entirely. 🙃</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb361" data-code-line-numbers="" style="background: #f1f3f5;"><pre class="sourceCode py code-with-copy"><code class="sourceCode python"><span id="cb361-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">class</span> Dataset():</span>
<span id="cb361-2">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__init__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, x, y): <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.x, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> x, y</span>
<span id="cb361-3">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__len__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.x)</span>
<span id="cb361-4">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">__getitem__</span>(<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>, i): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.x[i], <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">self</span>.y[i]</span></code></pre></div></div>
<div id="6c237fd3" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb362" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb362-1">trn_ds[[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>]]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="237">
<pre data-code-line-numbers=""><code>(tensor([[0., 0., 0.,  ..., 0., 0., 0.],
         [0., 0., 0.,  ..., 0., 0., 0.],
         [0., 0., 0.,  ..., 0., 0., 0.]]),
 tensor([9, 1, 3]))</code></pre>
</div>
</div>
<div id="374e3ea5" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb364" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb364-1">trn_dl <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataLoader(trn_ds, sampler<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>trn_samp)</span>
<span id="cb364-2">vld_dl <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> DataLoader(vld_ds, sampler<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>vld_samp)</span></code></pre></div></div>
</div>
<div id="ae0059d4" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb365" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb365-1">xb, yb <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">next</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">iter</span>(trn_dl))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> xb.shape, yb.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="239">
<pre data-code-line-numbers=""><code>(torch.Size([1, 50, 784]), torch.Size([1, 50]))</code></pre>
</div>
</div>
</section>
</section>
<section id="validation" class="level2">
<h2 class="anchored" data-anchor-id="validation">Validation</h2>
<p>When training and evaluating a model, <code>model.train()</code> and <code>model.eval()</code> need to be called respectively. These methods are used by layers such as <code>nn.BatchNorm2d</code> and <code>nn.Dropout</code> to ensure appropriate behaviour during different phases of the process.</p>
<div id="98e75494" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb367" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb367-1">?model.train</span></code></pre></div></div>
</div>
<div id="2fa3d54b" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb368" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb368-1">?model.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">eval</span></span></code></pre></div></div>
</div>
<div id="b0b4fc5d" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb369" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb369-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> fit(epochs, model, loss_func, opt, train_dl, valid_dl):</span>
<span id="cb369-2">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> epoch <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(epochs):</span>
<span id="cb369-3">    model.train()</span>
<span id="cb369-4">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> xb, yb <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> train_dl:</span>
<span id="cb369-5">      preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(xb)</span>
<span id="cb369-6">      loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss_func(preds, yb)</span>
<span id="cb369-7">      loss.backward()</span>
<span id="cb369-8">      opt.step()</span>
<span id="cb369-9">      opt.zero_grad()</span>
<span id="cb369-10">    </span>
<span id="cb369-11">    model.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">eval</span>()</span>
<span id="cb369-12">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">with</span> torch.no_grad():</span>
<span id="cb369-13">      tot_loss, tot_acc, count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.</span>,) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span></span>
<span id="cb369-14">      <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> xb, yb <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> valid_dl:</span>
<span id="cb369-15">        preds <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> model(xb)</span>
<span id="cb369-16">        n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(xb)</span>
<span id="cb369-17">        count <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> n</span>
<span id="cb369-18">        tot_loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> loss_func(preds, yb).item() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n</span>
<span id="cb369-19">        tot_acc  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> accuracy (preds, yb).item() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> n</span>
<span id="cb369-20">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(epoch, tot_loss<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>count, tot_acc<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>count)</span>
<span id="cb369-21">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> tot_loss<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>count, tot_acc<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>count</span></code></pre></div></div>
</div>
<div id="98707048" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb370" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb370-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> get_dls(trainn_ds, valid_ds, bs, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs):</span>
<span id="cb370-2">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> (DataLoader(trn_ds, batch_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>bs,   shuffle<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs),</span>
<span id="cb370-3">          DataLoader(vld_ds, batch_size<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>bs<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>,               <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>kwargs))</span></code></pre></div></div>
</div>
<div id="fb693b66" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb371" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb371-1">trn_dl, vld_dl <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_dls(trn_ds, vld_ds, bs)</span>
<span id="cb371-2">model, opt <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> get_model()</span></code></pre></div></div>
</div>
<div id="c37d0560" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb372" data-source-line-numbers="nil" data-code-line-numbers="nil" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb372-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>time loss, acc <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> fit(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, model, loss_func, opt, trn_dl, vld_dl)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre data-code-line-numbers=""><code>0 1.3015430688858032 0.6180000007152557
1 0.7089294970035553 0.7680000007152558
2 0.6260120451450348 0.7990000009536743
3 0.501511612534523 0.8490000128746032
4 0.5909725487232208 0.8119999945163727
CPU times: user 1.55 s, sys: 41.8 ms, total: 1.59 s
Wall time: 358 ms</code></pre>
</div>
</div>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>If you have any comments, questions, suggestions, feedback, criticisms, or corrections, please do post them down in the comment section below!</p>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Creating Models</category>
  <category>Programming</category>
  <category>Python</category>
  <category>PyTorch</category>
  <category>fastai</category>
  <guid>https://forbo7.github.io/forblog/posts/20_models_from_scratch.html</guid>
  <pubDate>Sun, 26 May 2024 00:00:00 GMT</pubDate>
  <media:content url="https://forbo7.github.io/forblog/images/20_model_from_scratch/thumbnail.jpeg" medium="image" type="image/jpeg"/>
</item>
<item>
  <title>A Brief Token on Tokenizers</title>
  <dc:creator>Salman Naqvi</dc:creator>
  <link>https://forbo7.github.io/forblog/posts/19_tokenizers.html</link>
  <description><![CDATA[ 




<blockquote class="blockquote">
<p>This notebook follows the <a href="https://docs.fast.ai/dev/style.html">fastai style guide</a>.</p>
</blockquote>
<p><img src="https://forbo7.github.io/forblog/images/19_tokenizers/thumbnail.png" class="img-fluid"></p>
<p>Tokenization is the process whereby text is given a numerical representation. Sentences are split into components known as tokens. These tokens represent numerical values that language models can work with.</p>
<p>There are various approaches to tokenization. Examples include:</p>
<ul>
<li>word-based tokenization</li>
<li>character-based tokenization</li>
<li>subword-based tokenization</li>
<li>and a whole lot more.</li>
</ul>
<p>Language models require the use of their own tokenization technique to properly work. Let’s have a look at three approaches.</p>
<section id="word-based" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="word-based">Word-based</h2>
<p>The word-based approach, well, splits sentences into individual words. In some cases, it also splits on punctuation.</p>
<p>In the example below, the sentence is tokenized into its words using whitespace.</p>
<div id="cell-6" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;colab&quot;,&quot;value&quot;:{&quot;base_uri&quot;:&quot;https://localhost:8080/&quot;}}" data-outputid="e2ac5d36-aca7-4b93-ecc1-a26600b00266" data-execution_count="1">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"I'm really excited doing this, you know?"</span>.split()</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="1">
<pre><code>["I'm", 'really', 'excited', 'doing', 'this,', 'you', 'know?']</code></pre>
</div>
</div>
<p>Let’s see it split based on its punctuation.</p>
<div id="cell-8" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;colab&quot;,&quot;value&quot;:{&quot;base_uri&quot;:&quot;https://localhost:8080/&quot;}}" data-outputid="df4cc4a8-490f-4d3f-f2c2-5daa149303cd" data-execution_count="2">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> re</span>
<span id="cb3-2"></span>
<span id="cb3-3">seq <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"I'm really excited doing this, you know?"</span></span>
<span id="cb3-4">toks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> re.findall(<span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">r'</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">\w</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">|</span><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">[^</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">\w\s</span><span class="pp" style="color: #AD0000;
background-color: null;
font-style: inherit;">]</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="vs" style="color: #20794D;
background-color: null;
font-style: inherit;">'</span>, seq)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> toks</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="2">
<pre><code>['I', "'", 'm', 'really', 'excited', 'doing', 'this', ',', 'you', 'know', '?']</code></pre>
</div>
</div>
<p>After tokenizing, an ID is assigned to each word, or token, so the model can identify them.</p>
<p>The issue with the word-based approach is wend up with huge vocabularies<sup>1</sup>, especially when splitting on punctuation. For instance, the English language has over 500,000 words, so we would also need more than 500,000 tokens.</p>
<div class="no-row-height column-margin column-container"><div id="fn1"><p><sup>1</sup>&nbsp;A vocabulary is a collection of tokens.</p></div><div id="fn2"><p><sup>2</sup>&nbsp;Examples of such tokens include [UNK] or &lt;unk&gt;.</p></div></div><p>To remedy this, we could use only the <img src="https://latex.codecogs.com/png.latex?x"> most frequently used words However, the issue that arises here is when the tokenizer encounters a word not present in its vocabulary. In this situation, a token representing the concept of “unknown” would be assigned<sup>2</sup>. When there are many such tokens, the model has no way of “knowing” that these tokens in fact represent different words.</p>
<p>Another issue with this approach is that the tokenizer will assign words such as “car” and “cars” different tokens. The model will not know that these two words are actually similar and represent almost the same concept.</p>
</section>
<section id="character-based" class="level2">
<h2 class="anchored" data-anchor-id="character-based">Character-based</h2>
<p>This approach splits text into characters, resulting in a much, much smaller vocabulary – the English alphabet only has 26 letters, as opposed to hundreds of thousands of words. It also results in fewer unknown tokens as words are comprised from everything within the vocabulary.</p>
<div id="cell-12" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;colab&quot;,&quot;value&quot;:{&quot;base_uri&quot;:&quot;https://localhost:8080/&quot;}}" data-outputid="857f71cd-b624-4a43-ee6a-ae9028d267d8" data-execution_count="3">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Who doesn't love tokenization!"</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="3">
<pre><code>['W',
 'h',
 'o',
 ' ',
 'd',
 'o',
 'e',
 's',
 'n',
 "'",
 't',
 ' ',
 'l',
 'o',
 'v',
 'e',
 ' ',
 't',
 'o',
 'k',
 'e',
 'n',
 'i',
 'z',
 'a',
 't',
 'i',
 'o',
 'n',
 '!']</code></pre>
</div>
</div>
<p>However, this approach also has its drawbacks. Individual characters hold less meaning than a whole word. For example, ‘t’ holds less meaning than ‘tokenization’.</p>
<p>That said, this issue is not as prevalent in other languages. In Chinese languages, each character is also a word. Therefore, characters in Chinese languages hold less meaning than characters in Latin languages.</p>
<p>While there will be an overall smaller vocabulary, there will still be much processing to do – we end up with a large amount of individual tokens to process. ‘Hello!’ would need only a single token, where as ‘H’, ‘e’, ‘l’, ‘l’, ‘o’, and ‘!’ would require six tokens.</p>
</section>
<section id="subword-based" class="level2">
<h2 class="anchored" data-anchor-id="subword-based">Subword-based</h2>
<p>This approach is a combination of the two approaches above, and is also the approach most state-of-the-art tokenizers use today.</p>
<p>With subword-based tokenizers, words fall into two categories: frequent words and rare words. Frequent words are not to be split, but rare words are to be split into meaningful subwords.</p>
<p><img src="https://forbo7.github.io/forblog/images/19_tokenizers/1.png" class="img-fluid"></p>
<p>For example, ‘tokenization’ would be categorized as a rare word and would be tokenized into the tokens ‘token’ and ‘ization’. Though one word is now represented by two tokens, as opposed to a single token with the word-based approach, it is split into two components that much more frequently appear. We also don’t need eleven tokens, as would be with the character-based approach. On top of that, the model would learn the grammatical function of ‘ization’.</p>
<p>This is all while giving the model the ability to learn the meaning of ‘realization’ as the two tokens that comprise the word appear next to each other</p>
<p>This approach allows us to have relatively good covereage for a language while having relatively smaller vocabularies. It also results in minimal unknown tokens.</p>
</section>
<section id="tokenizing-time" class="level2">
<h2 class="anchored" data-anchor-id="tokenizing-time">Tokenizing Time</h2>
<p>If we draw parallels between a tokenizer and a model, the algorithm of a tokenizer is akin to the architecture of a model. On a similar note, the vocabulary of a tokenizer is akin to the weights of a model.</p>
<p>Let’s load in the tokenizer used for the <a href="https://huggingface.co/bert-base-cased">BERT base model (cased)</a>.</p>
<div id="cell-19" class="cell" data-execution_count="4">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">!</span> pip install <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>Uqq transformers</span></code></pre></div></div>
</div>
<div id="cell-20" class="cell" data-execution_count="5">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="annotated-cell-5" style="background: #f1f3f5;"><pre class="sourceCode python code-annotation-code code-with-copy code-annotated"><code class="sourceCode python"><a class="code-annotation-anchor" data-target-cell="annotated-cell-5" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-5-1" class="code-annotation-target"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> logging<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> logging.disable(logging.WARNING)</span>
<span id="annotated-cell-5-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> transformers <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> AutoTokenizer</span>
<span id="annotated-cell-5-3"></span>
<span id="annotated-cell-5-4">tokz <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> AutoTokenizer.from_pretrained(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'bert-base-cased'</span>)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
<div class="cell-annotation">
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-5" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-5" data-code-lines="1" data-code-annotation="1">HuggingFace is verbose.</span>
</dd>
</dl>
</div>
</div>
<p>We can use the loaded tokenizer to directly tokenize our desired sequence.</p>
<div id="cell-23" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;colab&quot;,&quot;value&quot;:{&quot;base_uri&quot;:&quot;https://localhost:8080/&quot;}}" data-outputid="54c37ef9-3702-4dcd-c2cc-1cc2f576ff05" data-execution_count="6">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1">seq <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"The process of tokenization has lead me to the appalling conclusion: life isn't what it is."</span></span>
<span id="cb8-2">tokz(seq)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="6">
<pre><code>{'input_ids': [101, 1109, 1965, 1104, 22559, 2734, 1144, 1730, 1143, 1106, 1103, 12647, 5727, 1158, 6593, 131, 1297, 2762, 112, 189, 1184, 1122, 1110, 119, 102], 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}</code></pre>
</div>
</div>
<p>However, let’s look behind the scenes to see what’s happening. We’ll only focus on how <code>input_ids</code> came to be.</p>
</section>
<section id="behind-the-scenes" class="level2">
<h2 class="anchored" data-anchor-id="behind-the-scenes">Behind the Scenes</h2>
<section id="encoding" class="level3">
<h3 class="anchored" data-anchor-id="encoding">Encoding</h3>
<p>Encoding is the name given to the process whereby text is mapped to numbers. Text is first tokenized, after which, the tokens are mapped to their respective IDs.</p>
<section id="tokenization" class="level4">
<h4 class="anchored" data-anchor-id="tokenization">Tokenization</h4>
<div id="cell-29" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;colab&quot;,&quot;value&quot;:{&quot;base_uri&quot;:&quot;https://localhost:8080/&quot;}}" data-outputid="86d16c18-36e7-4741-c9c8-5c3c3a6a1687" data-execution_count="7">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1">toks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tokz.tokenize(seq)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> toks</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="7">
<pre><code>['The',
 'process',
 'of',
 'token',
 '##ization',
 'has',
 'lead',
 'me',
 'to',
 'the',
 'app',
 '##all',
 '##ing',
 'conclusion',
 ':',
 'life',
 'isn',
 "'",
 't',
 'what',
 'it',
 'is',
 '.']</code></pre>
</div>
</div>
<p>As we can see, the tokenizer used by the BERT base model (cased) is a subword-based tokenizer. This can be seen by ‘tokenization’ being split into ‘token’ and ‘##ization’, as well as ‘appalling’ being split into ‘app’, ‘##all’, and ‘##ing’.</p>
</section>
<section id="tokens-to-ids" class="level4">
<h4 class="anchored" data-anchor-id="tokens-to-ids">Tokens to IDs</h4>
<div id="cell-32" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;colab&quot;,&quot;value&quot;:{&quot;base_uri&quot;:&quot;https://localhost:8080/&quot;}}" data-outputid="1e775139-627e-4994-d613-f8842dfb23f7" data-execution_count="8">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1">ids <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tokz.convert_tokens_to_ids(toks)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> ids</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="8">
<pre><code>[1109,
 1965,
 1104,
 22559,
 2734,
 1144,
 1730,
 1143,
 1106,
 1103,
 12647,
 5727,
 1158,
 6593,
 131,
 1297,
 2762,
 112,
 189,
 1184,
 1122,
 1110,
 119]</code></pre>
</div>
</div>
<p>The numbers that have been assigned are based on the vocabulary of the tokenizer. These IDs can now be used as input to a model.</p>
</section>
</section>
</section>
<section id="decoding" class="level2">
<h2 class="anchored" data-anchor-id="decoding">Decoding</h2>
<p>Decoding is simply the opposite process: convert a sequence of IDs into their respective tokens, including putting together tokens that were part of the same word.</p>
<div id="cell-36" class="cell" data-quarto-private-1="{&quot;key&quot;:&quot;colab&quot;,&quot;value&quot;:{&quot;base_uri&quot;:&quot;https://localhost:8080/&quot;,&quot;height&quot;:53}}" data-outputid="c4f87052-7ff4-4e56-972b-47103df0d782" data-execution_count="9">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb14" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1">dec_seq <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tokz.decode(ids)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> dec_seq</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="9">
<pre><code>"The process of tokenization has lead me to the appalling conclusion : life isn't what it is."</code></pre>
</div>
</div>
<p>The decoding algorithm of our tokenzier has introduced a space before the colon. 🤔</p>
<p>Decoding is used for models that generate text: the model outputs a sequence of IDs which are then decoded to their respective tokens.</p>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>Tokenization is all about splitting text up and giving the split up text a numerical representation that computers can work with.</p>
<p>If you have any comments, questions, suggestions, feedback, criticisms, or corrections, please do post them down in the comment section below!</p>


</section>


<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>LLMs</category>
  <category>Transformers</category>
  <guid>https://forbo7.github.io/forblog/posts/19_tokenizers.html</guid>
  <pubDate>Wed, 24 Jan 2024 00:00:00 GMT</pubDate>
  <media:content url="https://forbo7.github.io/forblog/images/19_tokenizers/thumbnail.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>Backpropagation Explained using English Words*</title>
  <dc:creator>Salman Naqvi</dc:creator>
  <link>https://forbo7.github.io/forblog/posts/18_backprop_from_scratch.html</link>
  <description><![CDATA[ 




<p><em><strong>This post was edited on Wednesday, 9 August 2023</strong></em></p>
<p><img src="https://forbo7.github.io/forblog/images/18_backprop_from_scratch/thumbnail.png" class="img-fluid" alt="A red rocket ship being propelled through space by mathematical symbols propagating out of its boosters."></p>
<div class="callout callout-style-simple callout-note">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>This post would not be possible if not for the elegant deconstruction of backpropagation in fastai Course Part 2 taught by <a href="https://solve.it.com/#im-jeremy-howard-from-fastai">Jeremy Howard</a>, and for the elegant deconstruction also present in [The Matrix Calculus You Need for Deep Learning] by <a href="https://www.linkedin.com/in/terence-parr/">Terence Parr</a> and also Jeremy Howard.</p>
</div>
</div>
</div>
<div class="callout callout-style-simple callout-important">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>This guide assumes a basic understanding of derivatives and matrices.</p>
</div>
</div>
</div>
<p>Backpropagation sounds and looks daunting. It doesn’t need to be. In fact, backpropagation is really just a fancy word for the chain rule. Implementing a backpropagation algorithm is simply implementing one big fat chain rule equation.</p>
<p>Let’s remind ourselves of the chain rule. The chain rule lets us figure out how much a given variable indirectly changes with respect to another variable. Take the example below.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Balign%7D%0A%20%20y%20&amp;=%203u%20%5C%5C%0A%20%20u%20&amp;=%207%20+%20x%5E2%0A%5Cend%7Balign%7D%0A"></p>
<p>We want to figure out how much <img src="https://latex.codecogs.com/png.latex?y"> changes with each increment in <img src="https://latex.codecogs.com/png.latex?x">. The problem is that <img src="https://latex.codecogs.com/png.latex?x"> doesn’t direcly change <img src="https://latex.codecogs.com/png.latex?y">. Rather, <img src="https://latex.codecogs.com/png.latex?x"> changes <img src="https://latex.codecogs.com/png.latex?u"> which in turn changes <img src="https://latex.codecogs.com/png.latex?y">.</p>
<p>The chain rule allows us to solve this problem. In this case, the chain rule tells us that we can figure out how much <img src="https://latex.codecogs.com/png.latex?x"> indirecly changes <img src="https://latex.codecogs.com/png.latex?y"> by multiplying the derivative of <img src="https://latex.codecogs.com/png.latex?y"> with respect to <img src="https://latex.codecogs.com/png.latex?u">, and the derivative of <img src="https://latex.codecogs.com/png.latex?u"> with respect to <img src="https://latex.codecogs.com/png.latex?x">.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7Bdy%7D%7Bdx%7D%20=%20%5Cfrac%7Bdy%7D%7Bdu%7D%20%5Ccdot%20%5Cfrac%7Bdu%7D%7Bdx%7D%0A"></p>
<p>Aaand I’ve just described backpropagation in a nutshell. That’s all there really is to it. The only difference is that in a neural network there are many more intermediate variables and functions, and that we want to find out how the weights indirectly change the loss.</p>
<p>Let’s see this tangibly in action.</p>
<p>We have the following neural network comprised of two layers: the first layer contains the affine function<sup>1</sup> together with the ReLU, while the second layer contains only the affine function. The loss, which is MSE (Mean Squared Error), will then be calculated from the output of the second layer.</p>
<div class="no-row-height column-margin column-container"><div id="fn1"><p><sup>1</sup>&nbsp;Affine function is a fancy name for the linear function</p></div></div><div class="cell" data-layout-align="default">
<div class="cell-output-display">
<div>
<p></p><figure class="figure"><p></p>
<div>
<pre class="mermaid mermaid-js">flowchart LR
  subgraph A [Layer 1]
    direction LR
    id1[Affine Function] --&gt; id2[ReLU]
  end

  subgraph B [Layer 2]
    direction LR
    id2 --&gt; id3[Affine Function]
  end
  
  subgraph C [Loss Function]
    direction LR
    id3 --&gt; id4[MSE]
  end
</pre>
</div>
<p></p></figure><p></p>
</div>
</div>
</div>
<p>Mathematically speaking, the first layer with a single sample <img src="https://latex.codecogs.com/png.latex?x"> looks like this.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Ctext%7Bmax%7D(0,%20x%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%0A"></p>
<p>The second layer looks like this.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Ctext%7Bmax%7D(0,%20x%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2%0A"></p>
<p>And the loss function looks like this.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7B(y%20-%20(%5Ctext%7Bmax%7D(0,%20x%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2))%5E2%7D%7B2%7D%0A"></p>
<div class="callout callout-style-simple callout-note">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>MSE in its most basic form looks like this. <img src="https://latex.codecogs.com/png.latex?%0A%5Ctext%7BMSE%7D%20=%20%5Cfrac%7B(y%20-%20x)%5E2%7D%7B1%7D%0A"></p>
<p>If we have multiple data points, then it looks like this.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Ctext%7BMSE%7D%20=%20%5Cfrac%7B(y_1%20-%20x_1)%5E2+(y_2%20-%20x_2)%5E2+(y_3%20-%20x_3)%5E2%7D%7B3%7D%0A"></p>
</div>
</div>
</div>
<p>However, when working with multiple samples, the mean squared error comes out looking like this, where <img src="https://latex.codecogs.com/png.latex?N"> represents the total number of samples.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7B(%5Cvec%7B%5Crm%7By%7D%7D_1%20-%20(%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_1%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2))%5E2%20+%20(%5Cvec%7B%5Crm%7By%7D%7D_2%20-%20(%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_2%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2))%5E2%20+%20%5Ccdots%20+%20(%5Cvec%7B%5Crm%7By%7D%7D_N%20-%20(%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_N%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2))%5E2%7D%7BN%7D%0A"></p>
<p>Or more simply…<sup>2</sup></p>
<div class="no-row-height column-margin column-container"><div id="fn2"><p><sup>2</sup>&nbsp;<img src="https://latex.codecogs.com/png.latex?%5Csum"> is known as the summation or sigma operator. If we have the equation <img src="https://latex.codecogs.com/png.latex?%5Csum%5E4_%7Bx=1%7D2x">, it means sum the equation <img src="https://latex.codecogs.com/png.latex?2x"> for all values of <img src="https://latex.codecogs.com/png.latex?x"> from 1 to 4. Find out more <a href="https://www.mathsisfun.com/algebra/sigma-notation.html">here</a>.</p></div></div><p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7B%5Csum%5EN_%7Bi=1%7D%20(%5Cvec%7B%5Crm%7By%7D%7D_i%20-%20(%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2))%5E2%7D%7BN%7D%0A"></p>
<p>…or even more simply.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7B1%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20(%5Cvec%7B%5Crm%7By%7D%7D_i%20-%20(%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2))%5E2%0A"></p>
<p>Our goal for the rest of this guide is to derive the gradients of <img src="https://latex.codecogs.com/png.latex?w_1">.</p>
<p>The equation above looks quite the mouthful though. One might even say scary. How would you even apply the chain rule here? How would you use the chain rule to derive the gradients of the weights and biases?</p>
<p>Let’s simplify things by introducing a bunch of intermediate variables. We’ll begin by substituting the innermost pieces of the equation, and then gradually make our way out.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Balign%7D%0A%20%20%20%20u_1%20&amp;=%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%5C%5C%0A%20%20%20%20u_2%20&amp;=%20%5Ctext%7Bmax%7D(0,%20u_1)%20%5C%5C%0A%20%20%20%20u_3%20&amp;=%20u_2%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2%20%5C%5C%0A%20%20%20%20u_4%20&amp;=%20%5Cvec%7B%5Crm%7By%7D%7D_i%20-%20u_3%20%5C%5C%0A%20%20%20%20u_5%20&amp;=%20u_4%5E2%0A%5Cend%7Balign%7D%0A"></p>
<p>The menacing equation above now gradually simplifies into the cute equation below.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Balign%7D%0A%20%20%20%20%5Ctext%7BMSE%7D%20&amp;=%20%5Cfrac%7B1%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20(%5Cvec%7B%5Crm%7By%7D%7D_i%20-%20(%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2))%5E2%20%5C%5C%0A%20%20%20%20&amp;=%20%5Cfrac%7B1%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20(%5Cvec%7B%5Crm%7By%7D%7D_i%20-%20(%5Ctext%7Bmax%7D(0,%20u_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2))%5E2%20%5C%5C%0A%20%20%20%20&amp;=%20%5Cfrac%7B1%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20(%5Cvec%7B%5Crm%7By%7D%7D_i%20-%20(u_2%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2))%5E2%20%5C%5C%0A%20%20%20%20&amp;=%20%5Cfrac%7B1%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20(%5Cvec%7B%5Crm%7By%7D%7D_i%20-%20u_3)%5E2%20%5C%5C%0A%20%20%20%20&amp;=%20%5Cfrac%7B1%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20(u_4)%5E2%20%5C%5C%0A%20%20%20%20&amp;=%20%5Cfrac%7B1%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20u_5%0A%5Cend%7Balign%7D%0A"></p>
<p>Very cute, hey?</p>
<p>In this cuter version of the equation, it is visible that incrementing <img src="https://latex.codecogs.com/png.latex?%5Cvec%7B%5Crm%7Bw%7D%7D_1"> does not directly change the MSE. Rather, incrementing <img src="https://latex.codecogs.com/png.latex?%5Cvec%7B%5Crm%7Bw%7D%7D_1"> changes <img src="https://latex.codecogs.com/png.latex?u_1">, which changes <img src="https://latex.codecogs.com/png.latex?u_2">, which changes <img src="https://latex.codecogs.com/png.latex?u_3">, which changes <img src="https://latex.codecogs.com/png.latex?u_4">, which in turn changes <img src="https://latex.codecogs.com/png.latex?u_5">.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7B%5Cpartial%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%7D%20%5Ctext%7BMSE%7D%20=%20%5Cfrac%7B%5Cpartial%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%7D%20%5Cfrac%7B1%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20u_5%20=%20%5Cfrac%7B1%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20%5Cfrac%7B%5Cpartial%20u%5E5%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%7D%20=%20%5Cfrac%7B1%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20%5Cfrac%7B%5Cpartial%20u_5%7D%7B%5Cpartial%20u_4%7D%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_4%7D%7B%5Cpartial%20u_3%7D%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_3%7D%7B%5Cpartial%20u_2%7D%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_2%7D%7B%5Cpartial%20u_1%7D%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_1%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%7D%0A"></p>
<p>See? Just a big, fat, and simple chain rule problem.</p>
<div class="callout callout-style-simple callout-note">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p><img src="https://latex.codecogs.com/png.latex?%5Cpartial"> is a curly “d” and can be read as “curly d”, or simply as “d”. <img src="https://latex.codecogs.com/png.latex?%5Cpartial"> notation will be used below, due to a concept known as partial derivatives. We will not go into this concept here, however, <a href="https://www.mathsisfun.com/calculus/derivatives-partial.html">this</a> is a great brief rundown on partial derivatives.</p>
</div>
</div>
</div>
<p>Now we can tackle finding the gradients for <img src="https://latex.codecogs.com/png.latex?w_1">. To do so, let’s find the gradients of each intermediate variable.<sup>3</sup> <sup>4</sup></p>
<div class="no-row-height column-margin column-container"><div id="fn3"><p><sup>3</sup>&nbsp;If needed, get a refresher of the derivative rules <a href="https://www.mathsisfun.com/calculus/derivatives-rules.html">here</a>.</p></div><div id="fn4"><p><sup>4</sup>&nbsp;<img src="https://latex.codecogs.com/png.latex?%5Cbegin%7Bcases%7D%5Cend%7Bcases%7D"> denotes a piecewise function. The most simplest piecewise function returns one calculation if a condition is met, and another calculation if the condition is not met. It can be thought of as an if-else statement in programming. Find out more <a href="https://www.mathsisfun.com/sets/functions-piecewise.html">here</a>.</p></div></div><p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Balign*%7D%0A%5Ctext%7Bgradient%20of%20%7D%20u_4%20&amp;=%20%5Cfrac%7B%5Cpartial%20u_5%7D%7B%5Cpartial%20u_4%7D%20&amp;&amp;=%20%5Cfrac%7B%5Cpartial%7D%7B%5Cpartial%20u_4%7D%20u_4%5E2%20&amp;&amp;&amp;=%202u_4%20%5C%5C%0A%5Ctext%7Bgradient%20of%20%7D%20u_3%20&amp;=%20%5Cfrac%7B%5Cpartial%20u_4%7D%7B%5Cpartial%20u_3%7D%20&amp;&amp;=%20%5Cfrac%7B%5Cpartial%7D%7B%5Cpartial%20u_3%7D%20%5Cvec%7B%5Crm%7By%7D%7D_i%20-%20u_3%20&amp;&amp;&amp;=%20-1%20%5C%5C%0A%5Ctext%7Bgradient%20of%20%7D%20u_2%20&amp;=%20%5Cfrac%7B%5Cpartial%20u_3%7D%7B%5Cpartial%20u_2%7D%20&amp;&amp;=%20%5Cfrac%7B%5Cpartial%7D%7B%5Cpartial%20u_2%7D%20u_2%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2%20&amp;&amp;&amp;=%20%5Cvec%7B%5Crm%7Bw%7D%7D%5ET_2%20%5C%5C%0A%5Ctext%7Bgradient%20of%20%7D%20u_1%20&amp;=%20%5Cfrac%7B%5Cpartial%20u_2%7D%7B%5Cpartial%20u_1%7D%20&amp;&amp;=%20%5Cfrac%7B%5Cpartial%7D%7B%5Cpartial%20u_1%7D%20%5Ctext%7Bmax%7D(0,%20u_1)%20&amp;&amp;&amp;=%0A%5Cbegin%7Bcases%7D%0A0%20&amp;%20u_1%20%E2%89%A4%200%20%5C%5C%0A1%20&amp;%20u_1%20%3E%200%0A%5Cend%7Bcases%7D%20%5C%5C%0A%5Ctext%7Bgradient%20of%20%7D%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20&amp;=%20%5Cfrac%7B%5Cpartial%20u_1%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%7D%20&amp;&amp;=%20%5Cfrac%7B%5Cpartial%7D%7B%5Cpartial%20w_1%7D%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20&amp;&amp;&amp;=%20%5Cvec%7B%5Crm%7Bx%7D%7D%5ET_i%0A%5Cend%7Balign*%7D%0A"></p>
<p>Now we multiply everything together.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7B%5Cpartial%20%5Ctext%7BMSE%7D%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%7D%20=%20%5Cfrac%7B%5Cpartial%20u_5%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%7D%20=%20%5Cfrac%7B1%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20(2u_4)%20%5Ccdot%20(-1)%20%5Ccdot%20%5Cleft(%5Cvec%7B%5Crm%7Bw%7D%7D%5ET_2%5Cright)%20%5Ccdot%20%5Cleft(%5Cbegin%7Bcases%7D%200%20&amp;%20u_1%20%E2%89%A4%200%20%5C%5C%201%20&amp;%20u_1%20%3E%200%20%5Cend%7Bcases%7D%5Cright)%20%5Ccdot%20%5Cleft(%5Cvec%7B%5Crm%7Bx%7D%7D%5ET_i%5Cright)%0A"></p>
<p>And it all eventually expands out to the following.</p>
<div class="callout callout-style-simple callout-note callout-titled">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-1-contents" aria-controls="callout-1" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Expansion
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-1" class="callout-1-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Balign%7D%0A%5Cfrac%7B%5Cpartial%20%5Ctext%7BMSE%7D%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%7D%20=%20%5Cfrac%7B%5Cpartial%20u_5%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%7D%20&amp;=%20%5Cfrac%7B1%7D%7BN%7D%5Csum%5EN_%7Bi=1%7D%20(2u_4)%20%5Ccdot%20(-1)%20%5Ccdot%20(%5Cvec%7B%5Crm%7Bw%7D%7D%5ET_2)%20%5Ccdot%20%5Cbegin%7Bcases%7D0%20&amp;%20u_1%20%E2%89%A4%200%20%5C%5C%201%20&amp;%20u_1%20%3E%200%5Cend%7Bcases%7D%20%5Ccdot%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%5ET%20%5C%5C%0A&amp;=%20%5Cfrac%7B1%7D%7BN%7D%5Csum%5EN_%7Bi=1%7D%20%5Cbegin%7Bcases%7D%200%20&amp;%20u_1%20%E2%89%A4%200%20%5C%5C%20-2u_4%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%5ET%20%5Ccdot%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%5ET%20&amp;%20u_1%20%3E%200%5Cend%7Bcases%7D%20%5C%5C%0A&amp;=%20%5Cfrac%7B1%7D%7BN%7D%5Csum%5EN_%7Bi=1%7D%20%5Cbegin%7Bcases%7D%200%20&amp;%20u_1%20%E2%89%A4%200%20%5C%5C%20-2(%5Cvec%7B%5Crm%7By%7D%7D_i%20-%20u_3)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%5ET%20%5Ccdot%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%5ET%20&amp;%20u_1%20%3E%200%5Cend%7Bcases%7D%20%5C%5C%0A&amp;=%20%5Cfrac%7B1%7D%7BN%7D%5Csum%5EN_%7Bi=1%7D%20%5Cbegin%7Bcases%7D%200%20&amp;%20u_1%20%E2%89%A4%200%20%5C%5C%20-2(%5Cvec%7B%5Crm%7By%7D%7D_i%20-%20(u_2%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2))%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%5ET%20%5Ccdot%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%5ET%20&amp;%20u_1%20%3E%200%5Cend%7Bcases%7D%20%5C%5C%0A&amp;=%20%5Cfrac%7B1%7D%7BN%7D%5Csum%5EN_%7Bi=1%7D%20%5Cbegin%7Bcases%7D%200%20&amp;%20u_1%20%E2%89%A4%200%20%5C%5C%20-2(%5Cvec%7B%5Crm%7By%7D%7D_i%20-%20(%5Ctext%7Bmax%7D(0,%20u_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2))%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%5ET%20%5Ccdot%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%5ET%20&amp;%20u_1%20%3E%200%5Cend%7Bcases%7D%20%5C%5C%0A&amp;=%20%5Cfrac%7B1%7D%7BN%7D%5Csum%5EN_%7Bi=1%7D%20%5Cbegin%7Bcases%7D%200%20&amp;%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%E2%89%A4%200%20%5C%5C%20-2(%5Cvec%7B%5Crm%7By%7D%7D_i%20-%20(%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2))%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%5ET%20%5Ccdot%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%5ET%20&amp;%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%3E%200%5Cend%7Bcases%7D%0A%5Cend%7Balign%7D%0A"></p>
</div>
</div>
</div>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7B%5Cpartial%20%5Ctext%7BMSE%7D%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%7D%20=%0A%5Cbegin%7Bcases%7D%0A%20%200%20&amp;%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%E2%89%A4%200%20%5C%5C%0A%20%20%5Cfrac%7B1%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20-2(%5Cvec%7B%5Crm%7By%7D%7D_i%20-%20%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D%5ET_2%20%5Ccdot%5Cvec%7B%5Crm%7Bx%7D%7D_i%5ET%20&amp;%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%3E%200%0A%5Cend%7Bcases%7D%0A"></p>
<p>We can further simplify by taking <img src="https://latex.codecogs.com/png.latex?-1"> and <img src="https://latex.codecogs.com/png.latex?2"> common.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7B%5Cpartial%20%5Ctext%7BMSE%7D%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%7D%20=%0A%5Cbegin%7Bcases%7D%0A%20%200%20&amp;%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%E2%89%A4%200%20%5C%5C%0A%20%20%5Cfrac%7B2%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20(%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2%20-%20%5Cvec%7B%5Crm%7By%7D%7D_i)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D%5ET_2%20%5Ccdot%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%5ET%20&amp;%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%3E%200%0A%5Cend%7Bcases%7D%0A"></p>
<p>We can simplify even further, by letting <img src="https://latex.codecogs.com/png.latex?e_i%20=%20%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2%20-%20%5Cvec%7B%5Crm%7By%7D%7D_i">.&nbsp;The <img src="https://latex.codecogs.com/png.latex?e"> stands for “error”.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7B%5Cpartial%20%5Ctext%7BMSE%7D%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%7D%20=%0A%5Cbegin%7Bcases%7D%0A%20%200%20&amp;%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%E2%89%A4%200%20%5C%5C%0A%20%20%5Cfrac%7B2%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20e_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D%5ET_2%20%5Ccdot%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%5ET%20&amp;%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%3E%200%0A%5Cend%7Bcases%7D%0A"></p>
<p>And there you go! We’ve derived the formula that will allow us to calculate the gradients of <img src="https://latex.codecogs.com/png.latex?%5Cvec%7B%5Crm%7Bw%7D%7D_1">.</p>
<hr>
<p>When implementing backpropagation in a program, it is often better to implement the entire equation in pieces, as opposed to a single line of code, through storing the result of each intermediate gradient. These intermediate gradients can be reused to calculate the gradients of another variable, such as the bias <img src="https://latex.codecogs.com/png.latex?b_1">.</p>
<p>Instead of implementing the following in a single line of code.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7B%5Cpartial%20u_5%7D%7B%5Cpartial%20u_4%7D%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_4%7D%7B%5Cpartial%20u_3%7D%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_3%7D%7B%5Cpartial%20u_2%7D%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_2%7D%7B%5Cpartial%20u_1%7D%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_1%7D%7B%5Cpartial%20%5Cvec%7Bw%7D_1%7D%0A"></p>
<p>We can instead first calculate the gradients of <img src="https://latex.codecogs.com/png.latex?u_4">.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Au_%7B4_g%7D%20=%20%5Cfrac%7B%5Cpartial%20u_5%7D%7B%5Cpartial%20u_4%7D%0A"></p>
<p>Then calculate the gradients of <img src="https://latex.codecogs.com/png.latex?u_3"> and multiply it with it with the gradients of <img src="https://latex.codecogs.com/png.latex?u_4">.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Au_%7B3_g%7D%20=%20u_%7B4_g%7D%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_4%7D%7B%5Cpartial%20u_3%7D%20=%20%5Cleft(%5Cfrac%7B%5Cpartial%20u_5%7D%7B%5Cpartial%20u_4%7D%5Cright)%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_4%7D%7B%5Cpartial%20u_3%7D%0A"></p>
<p>Then multiply the product above with the gradients of <img src="https://latex.codecogs.com/png.latex?u_2">.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Au_%7B2_g%7D%20=%20u_%7B3_g%7D%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_3%7D%7B%5Cpartial%20u_2%7D%20=%20%5Cleft(%5Cfrac%7B%5Cpartial%20u_5%7D%7B%5Cpartial%20u_4%7D%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_4%7D%7B%5Cpartial%20u_3%7D%5Cright)%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_3%7D%7B%5Cpartial%20u_2%7D%0A"></p>
<p>Then multiply the product above with the gradients of <img src="https://latex.codecogs.com/png.latex?u_1">.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Au_%7B1_g%7D%20=%20u_%7B2_g%7D%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_2%7D%7B%5Cpartial%20u_1%7D%20=%20%5Cleft(%5Cfrac%7B%5Cpartial%20u_5%7D%7B%5Cpartial%20u_4%7D%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_4%7D%7B%5Cpartial%20u_3%7D%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_3%7D%7B%5Cpartial%20u_2%7D%5Cright)%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_2%7D%7B%5Cpartial%20u_1%7D%0A"></p>
<p>And finally multiply the product above with the gradients of <img src="https://latex.codecogs.com/png.latex?%5Cvec%7B%5Crm%7Bw%7D%7D_1"></p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cvec%7B%5Crm%7Bw%7D%7D_%7B1_g%7D%20=%20u_%7B1_g%7D%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_1%7D%7B%5Cpartial%20%5Cvec%7Bw%7D_1%7D%20=%20%5Cleft(%5Cfrac%7B%5Cpartial%20u_5%7D%7B%5Cpartial%20u_4%7D%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_4%7D%7B%5Cpartial%20u_3%7D%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_3%7D%7B%5Cpartial%20u_2%7D%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_2%7D%7B%5Cpartial%20u_1%7D%5Cright)%20%5Ccdot%20%5Cfrac%7B%5Cpartial%20u_1%7D%7B%5Cpartial%20%5Cvec%7Bw%7D_1%7D%0A"></p>
<p>Let’s see this using Python instead.</p>
<p>The following is our neural network.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="annotated-cell-1" style="background: #f1f3f5;"><pre class="sourceCode python code-annotation-code code-with-copy code-annotated"><code class="sourceCode python"><a class="code-annotation-anchor" data-target-cell="annotated-cell-1" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-1-1" class="code-annotation-target">l1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> relu(lin(trn_x, w1, b1))</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-1" data-target-annotation="2" onclick="event.preventDefault();">2</a><span id="annotated-cell-1-2" class="code-annotation-target">l2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> lin(l1, w2, b2)</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-1" data-target-annotation="3" onclick="event.preventDefault();">3</a><span id="annotated-cell-1-3" class="code-annotation-target">loss <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> mse(l2, trn_y)</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-1" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-1" data-code-lines="1" data-code-annotation="1"><code>l1</code> is the first layer, <img src="https://latex.codecogs.com/png.latex?%5Ctext%7Bmax%7D(0,%20x%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)">.</span>
</dd>
<dt data-target-cell="annotated-cell-1" data-target-annotation="2">2</dt>
<dd>
<span data-code-cell="annotated-cell-1" data-code-lines="2" data-code-annotation="2"><code>l2</code> is the second layer, <img src="https://latex.codecogs.com/png.latex?%5Ctext%7Bmax%7D(0,%20x%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2%20=%20l_1%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2">.</span>
</dd>
<dt data-target-cell="annotated-cell-1" data-target-annotation="3">3</dt>
<dd>
<span data-code-cell="annotated-cell-1" data-code-lines="3" data-code-annotation="3"><code>loss</code> is the MSE, <img src="https://latex.codecogs.com/png.latex?%5Cfrac%7B1%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20(%5Cvec%7B%5Crm%7By%7D%7D_i%20-%20(%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2))%5E2%20=%20%5Cfrac%7B1%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20(%5Cvec%7B%5Crm%7By%7D%7D_i%20-%20l_2)%5E2">.</span>
</dd>
</dl>
<div class="callout callout-style-simple callout-note">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<div class="callout callout-style-simple callout-note no-icon callout-titled">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-2-contents" aria-controls="callout-2" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon no-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Substitutions
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-2" class="callout-2-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Balign%7D%0A%20%20%20%20u_1%20&amp;=%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%5C%5C%0A%20%20%20%20u_2%20&amp;=%20%5Ctext%7Bmax%7D(0,%20u_1)%20%5C%5C%0A%20%20%20%20u_3%20&amp;=%20u_2%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2%20%5C%5C%0A%20%20%20%20u_4%20&amp;=%20%5Cvec%7B%5Crm%7By%7D%7D_i%20-%20u_3%20%5C%5C%0A%20%20%20%20u_5%20&amp;=%20u_4%5E2%0A%5Cend%7Balign%7D%0A"></p>
</div>
</div>
</div>
<div class="callout callout-style-simple callout-note no-icon callout-titled">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-3-contents" aria-controls="callout-3" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon no-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Derivatives of the Substitutions
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-3" class="callout-3-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Balignat%7D%7B3%7D%0A%20%20%5Ctext%7Bgradient%20of%20%7D%20u_4%20&amp;=%20%5Cfrac%7B%5Cpartial%20u_5%7D%7B%5Cpartial%20u_4%7D%20&amp;&amp;=%0A%20%20%5Cfrac%7B%5Cpartial%7D%7B%5Cpartial%20u_4%7D%20u_4%5E2%20&amp;&amp;&amp;=%202u_4%20%5C%5C%0A%20%20%5Ctext%7Bgradient%20of%20%7D%20u_3%20&amp;=%20%5Cfrac%7B%5Cpartial%20u_4%7D%7B%5Cpartial%20u_3%7D%20&amp;&amp;=%20%5Cfrac%7B%5Cpartial%7D%7B%5Cpartial%20u_3%7D%20%5Cvec%7B%5Crm%7By%7D%7D_i%20-%20u_3%20&amp;&amp;&amp;=%20-1%20%5C%5C%0A%20%20%5Ctext%7Bgradient%20of%20%7D%20u_2%20&amp;=%20%5Cfrac%7B%5Cpartial%20u_3%7D%7B%5Cpartial%20u_2%7D%20&amp;&amp;=%20%5Cfrac%7B%5Cpartial%7D%7B%5Cpartial%20u_2%7D%20u_2%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2%20&amp;&amp;&amp;=%20%5Cvec%7B%5Crm%7Bw%7D%7D%5ET_2%20%5C%5C%0A%20%20%5Ctext%7Bgradient%20of%20%7D%20u_1%20&amp;=%20%5Cfrac%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bu%7D%7D_2%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bu%7D%7D_1%7D%20&amp;&amp;=%20%5Cfrac%7B%5Cpartial%7D%7B%5Cpartial%20u_1%7D%20%5Ctext%7Bmax%7D(0,%20u_1)%20&amp;&amp;&amp;=%0A%20%20%20%20%5Cbegin%7Bcases%7D%0A%20%20%20%20%20%200%20&amp;%20%5Cvec%7B%5Crm%7Bu%7D%7D_1%20%E2%89%A4%200%20%5C%5C%0A%20%20%20%20%20%201%20&amp;%20%5Cvec%7B%5Crm%7Bu%7D%7D_1%20%3E%200%0A%20%20%20%20%5Cend%7Bcases%7D%20%5C%5C%0A%20%20%5Ctext%7Bgradient%20of%20%7D%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20&amp;=%20%5Cfrac%7B%5Cpartial%20u_1%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%7D%20&amp;&amp;=%20%5Cfrac%7B%5Cpartial%7D%7B%5Cpartial%20w_1%7D%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20&amp;&amp;&amp;=%20%5Cvec%7B%5Crm%7Bx%7D%7D%5ET_i%0A%5Cend%7Balignat%7D%0A"></p>
</div>
</div>
</div>
</div>
</div>
</div>
<p>First we need to calculate the gradients of <img src="https://latex.codecogs.com/png.latex?u_4">.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="annotated-cell-2" style="background: #f1f3f5;"><pre class="sourceCode python code-annotation-code code-with-copy code-annotated"><code class="sourceCode python"><span id="annotated-cell-2-1">diff <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (trn_y <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> l2)</span>
<a class="code-annotation-anchor" data-target-cell="annotated-cell-2" data-target-annotation="1" onclick="event.preventDefault();">1</a><span id="annotated-cell-2-2" class="code-annotation-target">loss.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>trn_x.shape[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> diff</span><div class="code-annotation-gutter-bg"></div><div class="code-annotation-gutter"></div></code></pre></div></div>
<dl class="code-annotation-container-grid">
<dt data-target-cell="annotated-cell-2" data-target-annotation="1">1</dt>
<dd>
<span data-code-cell="annotated-cell-2" data-code-lines="2" data-code-annotation="1"><code>trn_x.shape[0]</code>, in this case, returns the total number of samples.</span>
</dd>
</dl>
<p>Next are the gradients of <img src="https://latex.codecogs.com/png.latex?u_3"></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1">diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> loss.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span></code></pre></div></div>
<p>Then the gradients of <img src="https://latex.codecogs.com/png.latex?u_2"></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1">l2.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> diff.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> w2.T</span></code></pre></div></div>
<p>Then the gradients of <img src="https://latex.codecogs.com/png.latex?u_1"></p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1">l1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> l2.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (l1 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&gt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>()</span></code></pre></div></div>
<p>And finally the gradients of <img src="https://latex.codecogs.com/png.latex?%5Cvec%7B%5Crm%7Bw%7D%7D_1">.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1">w1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (l1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> trn_x).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>()</span></code></pre></div></div>
<p>The equation for the gradient of <img src="https://latex.codecogs.com/png.latex?b_1"> is almost the same as the equation for the gradients of <img src="https://latex.codecogs.com/png.latex?w_1">, save for the last line where we do not have to matrix multiply with <img src="https://latex.codecogs.com/png.latex?%5Cvec%7B%5Crm%7Bx%7D%7D_i">. Therefore, we can reuse all previous gradient calculations to find the gradient of <img src="https://latex.codecogs.com/png.latex?b_1">.</p>
<div class="code-copy-outer-scaffold"><div class="sourceCode" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1">b1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (l1.g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>()</span></code></pre></div></div>
<div class="callout callout-style-simple callout-important">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>When multiplying various tensors together, make sure their shapes are compatible. Shape manipulations have been omitted above for simplicity.</p>
</div>
</div>
</div>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>And that’s all there really is to backpropagation; think of it a one big chain rule problem.</p>
<p>To make sure you’ve got it hammered down, get out a pen and paper and derivate the equations that would compute the gradients of <img src="https://latex.codecogs.com/png.latex?%5Cvec%7B%5Crm%7Bx%7D%7D_i">, <img src="https://latex.codecogs.com/png.latex?b_1">, <img src="https://latex.codecogs.com/png.latex?%5Cvec%7B%5Crm%7Bw%7D%7D_2">, and <img src="https://latex.codecogs.com/png.latex?u_2"> respectively with respect to the MSE.</p>
<p>And if you really want to hammer down your understanding on what’s happening, then I highly recommend reading <a href="https://explained.ai/matrix-calculus/">The Matrix Calculus You Need For Deep Learning</a>. I’ve also <a href="https://forbo7.github.io/misc/matrix_calculus_practice.pdf">compiled backpropagation practice questions</a> from this paper!</p>
<div class="callout callout-style-simple callout-note callout-titled">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-4-contents" aria-controls="callout-4" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Answers
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-4" class="callout-4-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Balign%7D%0A%20%20%5Cfrac%7B%5Cpartial%20%5Ctext%7BMSE%7D%7D%7B%5Cpartial%20b_1%7D%20&amp;=%0A%20%20%20%20%5Cbegin%7Bcases%7D%0A%20%20%20%20%20%200%20&amp;%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%E2%89%A4%200%20%5C%5C%0A%20%20%20%20%20%20%5Cfrac%7B2%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20(%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2%20-%20%5Cvec%7B%5Crm%7By%7D%7D_i)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%5ET%20&amp;%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%3E%200%0A%20%20%20%20%5Cend%7Bcases%7D%20%5C%5C%0A%20%20%5Cfrac%7B%5Cpartial%20%5Ctext%7BMSE%7D%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%7D%20&amp;=%0A%20%20%20%20%5Cbegin%7Bcases%7D%0A%20%20%20%20%20%200%20&amp;%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%E2%89%A4%200%20%5C%5C%0A%20%20%20%20%20%20%5Cfrac%7B2%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20(%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2%20-%20%5Cvec%7B%5Crm%7By%7D%7D_i)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D%5ET_2%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%5ET%20&amp;%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1%20%3E%200%0A%20%20%20%20%5Cend%7Bcases%7D%20%5C%5C%0A%20%20%5Cfrac%7B%5Cpartial%20%5Ctext%7BMSE%7D%7D%7B%5Cpartial%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%7D%20&amp;=%20%5Cfrac%7B2%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20(%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2%20-%20%5Cvec%7B%5Crm%7By%7D%7D_i)%20%5Ccdot%20%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5C%5C%0A%20%20%5Cfrac%7B%5Cpartial%20%5Ctext%7BMSE%7D%7D%7B%5Cpartial%20b_2%7D%20&amp;=%20%5Cfrac%7B2%7D%7BN%7D%20%5Csum%5EN_%7Bi=1%7D%20%5Ctext%7Bmax%7D(0,%20%5Cvec%7B%5Crm%7Bx%7D%7D_i%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_1%20+%20b_1)%20%5Ccdot%20%5Cvec%7B%5Crm%7Bw%7D%7D_2%20+%20b_2%20-%20%5Cvec%7B%5Crm%7By%7D%7D_i%0A%5Cend%7Balign%7D%0A"></p>
</div>
</div>
</div>
<p>If you have any comments, questions, suggestions, feedback, criticisms, or corrections, please do post them down in the comment section below!</p>


</section>


<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Mathematics</category>
  <category>Creating Models</category>
  <guid>https://forbo7.github.io/forblog/posts/18_backprop_from_scratch.html</guid>
  <pubDate>Mon, 07 Aug 2023 00:00:00 GMT</pubDate>
  <media:content url="https://forbo7.github.io/forblog/images/18_backprop_from_scratch/thumbnail.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>Implementing and Optimizing Meanshift Clustering</title>
  <dc:creator>Salman Naqvi</dc:creator>
  <link>https://forbo7.github.io/forblog/posts/17_meanshift_clustering.html</link>
  <description><![CDATA[ 




<blockquote class="blockquote">
<p>This notebook follows the <a href="https://docs.fast.ai/dev/style.html">fastai style guide</a>.</p>
</blockquote>
<p><img src="https://forbo7.github.io/forblog/images/17_meanshift_clustering/thumbnail.png" class="img-fluid"></p>
<div class="callout callout-style-simple callout-note">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>This notebook is based on the contents taught in <a href="https://course.fast.ai/Lessons/lesson12.html">Lesson 12</a> of part 2 of the <a href="https://course.fast.ai/Lessons/part2.html">fastai Course</a>, by <a href="https://solve.it.com/#im-jeremy-howard-from-fastai">Jeremy Howard</a> who created the first LLM, ULMFiT in 2016.</p>
</div>
</div>
</div>
<p>Meanshift clustering is a technique for unsupervised learning. Give this algorithm a bunch of data and it will figure out what groups the data can be sorted into. It does this by iteratively moving all data points until they converge to a single point.</p>
<p>The steps of the algorithm can be summarized as follows:</p>
<ol type="1">
<li>For each data point <img src="https://latex.codecogs.com/png.latex?x"> in the dataset, calculate the distance between <img src="https://latex.codecogs.com/png.latex?x"> and every other data point in the dataset.</li>
<li>Calculate weights for each point in the dataset by passing the calculated distances through the normal distribution.</li>
<li>Calculate the weighted average for all points in the dataset. This weighted average is the new location for <img src="https://latex.codecogs.com/png.latex?x"></li>
</ol>
<p>This is the data we will work with to illustrate meanshift clustering. The data points are put into clearly seperate clusters for the sake of clarity.</p>
<div id="5076d348" class="cell page-columns page-full">
<div class="cell-output cell-output-display column-page">
<div>                            <div id="dd6952c5-750c-4916-bf52-aaff6ab58e62" class="plotly-graph-div" style="height:576px; width:1024px;"></div>            <script type="text/javascript">                require(["plotly"], function(Plotly) {                    window.PLOTLYENV=window.PLOTLYENV || {};                                    if (document.getElementById("dd6952c5-750c-4916-bf52-aaff6ab58e62")) {                    Plotly.newPlot(                        "dd6952c5-750c-4916-bf52-aaff6ab58e62",                        [{"marker":{"color":"#636EFA","size":3},"mode":"markers","name":"cluster 0","x":[0.6106996536254883,4.454596519470215,2.0711617469787598,1.0110520124435425,4.5163893699646,-0.1486372947692871,4.0289177894592285,2.95975923538208,-1.0943694114685059,6.752066612243652,2.888312816619873,4.768091678619385,1.9764769077301025,-1.6155166625976562,-2.1650285720825195,-0.5145149230957031,2.2578015327453613,2.834491491317749,4.584721565246582,0.5921010971069336,-0.688715934753418,6.113814353942871,1.8596506118774414,3.565117835998535,2.0461254119873047,2.412180185317993,-4.187981128692627,1.7536394596099854,6.076658248901367,1.4662054777145386,5.0048909187316895,1.650177240371704,2.742509603500366,1.2938233613967896,-0.3352804183959961,1.1423156261444092,0.4638735055923462,3.4898533821105957,0.6288788318634033,0.12580561637878418,-2.603978157043457,3.7240519523620605,2.163062572479248,6.361776828765869,1.5535951852798462,4.1370134353637695,0.5990724563598633,3.5654516220092773,1.2442047595977783,4.808256149291992,2.729548692703247,1.533890962600708,3.3024158477783203,-0.2711365222930908,3.5784335136413574,3.4738755226135254,-0.07032990455627441,3.8442697525024414,1.1343374252319336,3.8752074241638184,0.6200094223022461,-0.2625694274902344,1.4806886911392212,3.077441453933716,3.7166671752929688,3.6967945098876953,1.9437216520309448,-2.3270368576049805,5.694780349731445,1.703410267829895,2.728020668029785,0.40372776985168457,3.029271125793457,5.021300315856934,7.112307548522949,4.243080139160156,2.595820188522339,1.5233139991760254,4.06235933303833,1.2589422464370728,3.9698963165283203,2.267824172973633,5.580748081207275,2.814542293548584,0.9386806488037109,0.8993861675262451,0.7550551891326904,4.578845024108887,1.3930007219314575,4.2748003005981445,4.01229190826416,3.0979256629943848,3.13167405128479,5.873199939727783,-2.3652734756469727,0.23277902603149414,1.6450698375701904,-0.16131353378295898,5.316432952880859,-0.746211051940918,-3.4459590911865234,4.096480369567871,4.127533912658691,2.5963215827941895,3.8091964721679688,0.47520267963409424,0.9366261959075928,3.342190980911255,-0.08721661567687988,1.2673484086990356,1.8158373832702637,5.756171226501465,3.4982364177703857,5.422142028808594,2.4125044345855713,3.337184429168701,-0.4337937831878662,2.2619690895080566,1.5083262920379639,1.9040424823760986,0.841778039932251,1.4697105884552002,1.0406396389007568,4.13149881362915,3.8440966606140137,1.5222117900848389,4.206725120544434,2.65280818939209,2.458773612976074,1.0481992959976196,4.258362770080566,4.151905059814453,-0.7333433628082275,1.8043519258499146,2.809670925140381,4.118513107299805,2.112030267715454,2.8926684856414795,3.7863731384277344,6.078733444213867,0.17786622047424316,3.2297608852386475,3.361069679260254,4.22938871383667,1.4906213283538818,2.156731367111206,3.407961368560791,1.0653377771377563,6.439641952514648,4.910748481750488,2.0400807857513428,5.018989086151123,3.889838695526123,3.167424201965332,4.468905448913574,4.915773391723633,3.9555795192718506,0.5957375764846802,3.816124439239502,-0.9412333965301514,-1.058197259902954,2.3830742835998535,3.87819766998291,0.6730018854141235,2.681736469268799,-0.7682609558105469,3.026716709136963,3.8628134727478027,3.148106813430786,3.167198657989502,5.090166091918945,2.068650245666504,3.3243465423583984,-0.19996142387390137,7.687468528747559,7.051206588745117,4.482922554016113,2.7472009658813477,1.6230460405349731,4.623526573181152,1.8923182487487793,2.9435620307922363,0.1830892562866211,2.60666561126709,3.119462251663208,6.189139366149902,-0.413712739944458,-1.0135910511016846,4.135379314422607,2.2551188468933105,5.880044937133789,0.2985837459564209,3.565070152282715,4.694297790527344,-0.8904917240142822,-0.025649309158325195,5.0980730056762695,1.2597852945327759,3.941540241241455,2.772353172302246,-0.18204474449157715,-0.41129565238952637,4.791975975036621,2.0827300548553467,2.2586898803710938,-0.25301527976989746,4.837216377258301,4.088098049163818,2.238393783569336,5.4800310134887695,3.3855934143066406,4.921282768249512,1.7489819526672363,1.8883492946624756,3.6563923358917236,4.024860382080078,2.62627911567688,7.209653377532959,-1.1760749816894531,1.2553073167800903,-0.571690559387207,4.939748287200928,0.19209623336791992,2.2359273433685303,1.525259017944336,3.8941426277160645,4.756255149841309,6.353114128112793,3.989452600479126,3.8916399478912354,6.344674110412598,1.3829160928726196,3.179715156555176,1.0047781467437744,6.336634635925293,3.4817066192626953,2.845355749130249,3.630941867828369,2.1003105640411377,5.563776016235352,-1.263171911239624,-1.5524673461914062,3.9684884548187256,5.099576473236084,3.5895919799804688,6.828782081604004,2.7350287437438965,0.5344339609146118,-0.6981027126312256,-0.6902151107788086],"y":[-20.19911766052246,-24.188343048095703,-20.4461612701416,-23.082050323486328,-22.281217575073242,-22.11271858215332,-18.81918716430664,-18.646093368530273,-21.80953025817871,-21.821704864501953,-19.33500862121582,-22.703832626342773,-21.56529426574707,-21.85576057434082,-19.576440811157227,-24.124313354492188,-21.136274337768555,-15.944525718688965,-22.563756942749023,-22.43811798095703,-18.182846069335938,-23.44659423828125,-21.643089294433594,-20.502317428588867,-21.664033889770508,-21.942182540893555,-23.455249786376953,-18.994644165039062,-21.080272674560547,-25.798601150512695,-21.938365936279297,-19.397350311279297,-20.67559242248535,-19.29376220703125,-24.924785614013672,-22.459728240966797,-18.407161712646484,-21.405635833740234,-21.948190689086914,-19.759958267211914,-20.179737091064453,-20.395484924316406,-23.22544288635254,-18.893400192260742,-21.470991134643555,-18.878507614135742,-20.718656539916992,-17.90732765197754,-19.23033905029297,-23.55394744873047,-21.126134872436523,-19.894866943359375,-16.80714225769043,-17.12339210510254,-21.43614959716797,-23.66242790222168,-21.786884307861328,-20.880727767944336,-22.178525924682617,-19.721088409423828,-18.49786949157715,-19.949764251708984,-19.712493896484375,-18.433025360107422,-20.785696029663086,-22.727603912353516,-22.862499237060547,-22.75919532775879,-24.530500411987305,-19.852903366088867,-24.47193717956543,-18.240379333496094,-21.417892456054688,-23.61248779296875,-22.270471572875977,-20.918540954589844,-22.311174392700195,-20.963150024414062,-23.506885528564453,-20.787317276000977,-23.379852294921875,-20.762178421020508,-22.015539169311523,-22.684114456176758,-22.676895141601562,-20.566917419433594,-21.35162353515625,-20.75017547607422,-22.98044776916504,-20.622966766357422,-22.628801345825195,-17.8162784576416,-19.385879516601562,-22.8177433013916,-23.94515609741211,-21.093578338623047,-20.66701889038086,-19.105106353759766,-22.95493507385254,-21.683509826660156,-21.13545036315918,-19.6022891998291,-19.796276092529297,-21.302955627441406,-23.10927391052246,-23.008304595947266,-27.83803367614746,-23.454715728759766,-25.18522071838379,-18.517133712768555,-22.626859664916992,-21.190433502197266,-19.635047912597656,-21.74361228942871,-22.370267868041992,-22.201234817504883,-21.50897789001465,-22.98897933959961,-20.32002067565918,-18.2002010345459,-19.156137466430664,-22.16558265686035,-16.592864990234375,-20.9410343170166,-21.66925048828125,-20.866079330444336,-22.89394187927246,-21.75556182861328,-24.45231819152832,-20.070878982543945,-14.87507152557373,-21.484704971313477,-23.4167423248291,-19.331729888916016,-22.969881057739258,-20.811262130737305,-17.795503616333008,-22.634695053100586,-22.771560668945312,-17.060901641845703,-23.224815368652344,-21.064428329467773,-21.073396682739258,-20.616165161132812,-19.296003341674805,-20.195350646972656,-23.40139389038086,-17.80548858642578,-21.35091209411621,-22.97028923034668,-21.86427116394043,-24.580934524536133,-22.574420928955078,-20.109445571899414,-20.246047973632812,-20.880678176879883,-22.15427589416504,-21.21795082092285,-21.609981536865234,-20.70313835144043,-20.49033546447754,-21.064477920532227,-19.699352264404297,-22.72942543029785,-19.058795928955078,-21.85211944580078,-20.760223388671875,-23.04998779296875,-23.362812042236328,-21.12179946899414,-17.609493255615234,-22.682052612304688,-22.00928497314453,-22.203414916992188,-23.86651611328125,-20.10556411743164,-24.718358993530273,-22.499277114868164,-24.465852737426758,-19.876663208007812,-21.51488494873047,-21.108518600463867,-18.40947914123535,-25.001358032226562,-19.844623565673828,-19.15580940246582,-21.532291412353516,-21.060213088989258,-21.3889217376709,-23.526735305786133,-18.872238159179688,-23.274763107299805,-21.09376335144043,-24.94708824157715,-22.410192489624023,-20.583330154418945,-17.562864303588867,-20.466636657714844,-17.395614624023438,-21.90605926513672,-20.758373260498047,-20.82671546936035,-13.170121192932129,-18.344348907470703,-24.698637008666992,-20.82878875732422,-24.995908737182617,-19.98826026916504,-20.985315322875977,-18.28809356689453,-18.92946434020996,-19.452714920043945,-20.269887924194336,-21.670387268066406,-21.58736801147461,-18.11713981628418,-22.169952392578125,-20.195409774780273,-19.091581344604492,-19.074148178100586,-18.046857833862305,-18.59525489807129,-21.3765926361084,-19.681989669799805,-24.445711135864258,-18.704004287719727,-17.731538772583008,-25.31211280822754,-22.73049545288086,-21.1287784576416,-21.608978271484375,-24.527162551879883,-22.626277923583984,-21.416810989379883,-23.346149444580078,-21.770475387573242,-23.14167594909668,-24.321273803710938,-24.238615036010742,-20.205543518066406,-18.339942932128906,-20.704547882080078,-20.283615112304688,-19.168262481689453,-19.91609001159668,-20.267263412475586,-20.524757385253906,-20.10521697998047,-17.82305145263672,-24.993026733398438],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[2.4445762634277344],"y":[-21.083776473999023],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[2.4445762634277344],"y":[-21.083776473999023],"type":"scatter"},{"marker":{"color":"#EF553B","size":3},"mode":"markers","name":"cluster 1","x":[9.87704086303711,9.4225435256958,12.610001564025879,8.097820281982422,11.419466972351074,10.570701599121094,10.606629371643066,10.462532043457031,11.331299781799316,11.382926940917969,11.107633590698242,14.95037841796875,13.36851692199707,15.071146011352539,8.195347785949707,8.854641914367676,11.516806602478027,15.112360000610352,9.312355995178223,12.523109436035156,14.841484069824219,15.487283706665039,10.850504875183105,12.387774467468262,11.285183906555176,11.804227828979492,10.544031143188477,13.17994499206543,14.77381420135498,11.45132827758789,9.2578706741333,13.98930835723877,11.58730697631836,9.93220329284668,12.861495971679688,10.736139297485352,9.71112060546875,12.424819946289062,13.16836929321289,11.584234237670898,5.022521495819092,11.749085426330566,11.312202453613281,10.611576080322266,13.377660751342773,9.172962188720703,12.465993881225586,9.5494384765625,18.93263816833496,9.865697860717773,7.6244330406188965,11.1902437210083,13.258797645568848,9.840498924255371,11.613204002380371,11.311509132385254,10.185104370117188,11.270140647888184,12.95288372039795,12.62736701965332,14.55495834350586,11.71548843383789,9.575156211853027,12.831417083740234,7.172362327575684,10.812312126159668,10.21819019317627,11.4874267578125,10.869904518127441,13.847227096557617,11.776945114135742,10.921489715576172,10.18920612335205,10.632547378540039,11.031829833984375,10.981271743774414,14.026257514953613,9.647284507751465,18.137493133544922,11.064699172973633,10.404289245605469,8.46476936340332,14.196146011352539,10.85347843170166,13.36893081665039,8.35534381866455,14.9078950881958,8.62026309967041,6.610985279083252,11.460588455200195,12.1513090133667,13.989845275878906,7.602276802062988,15.068745613098145,15.283571243286133,10.42579460144043,11.41176700592041,10.820887565612793,11.916272163391113,15.157073974609375,10.195613861083984,14.575783729553223,12.577715873718262,8.752012252807617,8.57979679107666,9.327132225036621,11.21414852142334,10.981815338134766,14.445018768310547,6.476677894592285,11.187596321105957,14.057319641113281,11.362394332885742,8.155521392822266,12.265863418579102,11.399274826049805,9.247962951660156,8.10108757019043,12.582670211791992,10.203760147094727,7.150644302368164,11.416135787963867,8.282318115234375,10.93171215057373,9.920757293701172,12.59582233428955,5.954134464263916,11.401212692260742,11.130741119384766,13.161144256591797,8.818209648132324,10.167387008666992,12.14991569519043,11.352355003356934,11.138047218322754,12.394486427307129,12.976234436035156,12.454710006713867,8.250981330871582,15.54655647277832,10.172869682312012,12.827277183532715,8.86609935760498,11.81514835357666,10.636499404907227,9.271520614624023,9.799882888793945,7.832983016967773,10.821706771850586,10.563729286193848,11.64404582977295,12.557385444641113,15.20111083984375,11.216188430786133,12.359991073608398,10.731277465820312,11.025440216064453,13.450078964233398,9.63072395324707,6.332091331481934,10.858210563659668,8.945043563842773,12.985211372375488,15.53884220123291,12.219693183898926,9.413066864013672,12.850086212158203,9.990818977355957,9.073244094848633,8.647806167602539,13.088233947753906,10.905885696411133,12.547986030578613,10.302464485168457,9.783677101135254,12.08859920501709,9.099506378173828,11.802888870239258,8.442436218261719,11.132010459899902,7.804447174072266,14.370488166809082,11.384010314941406,12.67867660522461,9.699455261230469,12.52734661102295,9.536325454711914,9.684154510498047,12.043754577636719,10.859668731689453,8.470977783203125,12.089127540588379,7.456197261810303,8.83816146850586,11.415051460266113,10.549241065979004,6.805138111114502,11.196460723876953,12.749780654907227,12.636879920959473,10.95596694946289,12.731612205505371,11.659228324890137,14.560370445251465,11.841026306152344,7.931714057922363,10.726155281066895,5.702099323272705,12.137916564941406,15.443826675415039,7.3869781494140625,10.457058906555176,11.095139503479004,8.380328178405762,11.541655540466309,9.862030982971191,15.231411933898926,12.802127838134766,12.960502624511719,12.770841598510742,10.196751594543457,10.122230529785156,5.181766986846924,8.951225280761719,10.136018753051758,5.531148910522461,8.604415893554688,7.1645731925964355,12.691882133483887,13.559928894042969,5.198024272918701,14.200967788696289,7.897911071777344,8.21728229522705,11.644851684570312,10.320767402648926,10.415617942810059,15.876169204711914,11.981152534484863,4.864884853363037,9.275575637817383,13.136369705200195,10.784153938293457,12.803083419799805,11.134258270263672,9.973132133483887,11.717573165893555,2.9842147827148438,10.181731224060059,10.367219924926758],"y":[10.734405517578125,9.335786819458008,13.441376686096191,12.330901145935059,10.063323020935059,11.657186508178711,7.365444660186768,8.999773025512695,12.038965225219727,14.764404296875,10.82178020477295,13.4752779006958,11.392098426818848,10.135046005249023,11.840617179870605,9.776314735412598,9.990473747253418,12.085968971252441,13.8656587600708,7.980899333953857,8.725305557250977,12.899062156677246,8.720598220825195,14.300816535949707,11.632344245910645,10.884347915649414,9.99297046661377,10.354414939880371,8.777225494384766,8.373196601867676,8.037626266479492,9.00489616394043,8.283859252929688,12.120036125183105,9.729784965515137,10.034659385681152,13.342782020568848,13.832403182983398,11.30892276763916,9.003535270690918,9.722219467163086,13.053757667541504,12.826997756958008,7.017003059387207,10.649638175964355,13.679852485656738,9.408282279968262,12.128579139709473,13.113380432128906,12.83919906616211,12.413917541503906,11.668290138244629,6.153925895690918,11.991576194763184,10.793174743652344,12.52327823638916,12.068902969360352,9.22436237335205,10.30783748626709,5.3423004150390625,10.344483375549316,14.47255802154541,7.237033367156982,12.807012557983398,12.02662467956543,12.13406753540039,12.714216232299805,11.554706573486328,11.308341026306152,7.09832763671875,13.935083389282227,11.023280143737793,11.676339149475098,10.078460693359375,8.887862205505371,8.004937171936035,12.172079086303711,8.344019889831543,10.546194076538086,10.278603553771973,9.850561141967773,6.540694236755371,14.094623565673828,13.03080940246582,12.026119232177734,9.844781875610352,14.854454040527344,9.092710494995117,7.083795547485352,13.150472640991211,8.925386428833008,9.54330825805664,12.065450668334961,13.750585556030273,10.335978507995605,14.149402618408203,10.169922828674316,14.469759941101074,12.803152084350586,10.56090259552002,10.896300315856934,10.610678672790527,10.40132999420166,10.194389343261719,9.682408332824707,8.019926071166992,12.813308715820312,7.141301155090332,8.150213241577148,10.157896995544434,10.739936828613281,8.905439376831055,12.959728240966797,14.031454086303711,13.927950859069824,15.988347053527832,8.539347648620605,11.02241039276123,11.853888511657715,10.494282722473145,11.071870803833008,12.508426666259766,10.966612815856934,11.251618385314941,12.862878799438477,11.168071746826172,11.423723220825195,7.485688209533691,14.271825790405273,13.000264167785645,12.808016777038574,8.910547256469727,4.895911693572998,7.373517036437988,14.97317886352539,11.791913032531738,10.086353302001953,12.438005447387695,12.250608444213867,8.70448112487793,9.40768051147461,8.550436019897461,8.311664581298828,11.452293395996094,9.780439376831055,12.431370735168457,12.913421630859375,8.143282890319824,9.135396957397461,11.134149551391602,6.741981029510498,9.244380950927734,10.749717712402344,14.637189865112305,12.528155326843262,9.443887710571289,14.947844505310059,7.758157730102539,13.048039436340332,10.627683639526367,10.81523609161377,10.374131202697754,9.01569652557373,14.85327434539795,8.898709297180176,11.091988563537598,8.544888496398926,13.079777717590332,12.462029457092285,6.712798595428467,9.902111053466797,10.244808197021484,7.307023048400879,9.82799243927002,9.81595230102539,12.278499603271484,12.8430757522583,14.464896202087402,10.822654724121094,10.515324592590332,11.292708396911621,10.368403434753418,9.722280502319336,11.41006088256836,14.371049880981445,12.479593276977539,11.51334285736084,9.181450843811035,11.381587028503418,11.955004692077637,8.314370155334473,13.114908218383789,14.425192832946777,11.066229820251465,9.404319763183594,14.337783813476562,7.97857666015625,9.011209487915039,15.631593704223633,11.388583183288574,14.366738319396973,11.034764289855957,8.076003074645996,9.505967140197754,12.511550903320312,8.819988250732422,7.850310325622559,19.094078063964844,13.645238876342773,12.414156913757324,10.631463050842285,10.430276870727539,9.743120193481445,10.801138877868652,9.165804862976074,13.029094696044922,10.357752799987793,8.63907241821289,6.381320953369141,9.96885871887207,8.676495552062988,14.108659744262695,10.252354621887207,10.053375244140625,9.217528343200684,11.634859085083008,10.610607147216797,13.862188339233398,14.077072143554688,12.144886016845703,6.061443328857422,9.93949031829834,14.236883163452148,11.515740394592285,9.876175880432129,12.265829086303711,4.3912739753723145,8.761274337768555,10.186405181884766,11.717260360717773,12.657522201538086,6.422496318817139,12.245983123779297,11.363253593444824,9.916359901428223,9.322500228881836,12.07647705078125,10.818828582763672,10.659802436828613,6.526799201965332],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[11.144817352294922],"y":[10.982318878173828],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[11.144817352294922],"y":[10.982318878173828],"type":"scatter"},{"marker":{"color":"#00CC96","size":3},"mode":"markers","name":"cluster 2","x":[-23.496248245239258,-19.102161407470703,-20.136016845703125,-16.482664108276367,-16.349597930908203,-19.713245391845703,-18.65350341796875,-13.829034805297852,-18.291528701782227,-19.674604415893555,-18.3510799407959,-17.09149932861328,-17.577880859375,-20.840408325195312,-17.026063919067383,-18.766075134277344,-18.991413116455078,-15.431722640991211,-15.667441368103027,-16.49349594116211,-18.01854705810547,-18.996410369873047,-20.137609481811523,-21.6656551361084,-18.331777572631836,-18.460737228393555,-17.945327758789062,-14.076920509338379,-22.975576400756836,-20.383657455444336,-16.282447814941406,-17.628402709960938,-18.828432083129883,-23.07760238647461,-17.44770622253418,-18.911293029785156,-17.204139709472656,-15.39111614227295,-15.860858917236328,-19.705379486083984,-20.822938919067383,-16.104167938232422,-15.548961639404297,-18.728506088256836,-15.924317359924316,-16.256725311279297,-18.9020938873291,-17.295326232910156,-19.94478988647461,-20.530868530273438,-18.124982833862305,-18.22002410888672,-16.544612884521484,-15.984344482421875,-21.301803588867188,-20.72646713256836,-19.2755126953125,-21.295223236083984,-17.879823684692383,-21.625612258911133,-23.16211700439453,-19.277111053466797,-21.854236602783203,-21.373796463012695,-20.612863540649414,-19.7716007232666,-18.101654052734375,-13.594627380371094,-15.992204666137695,-19.817270278930664,-19.524595260620117,-16.413419723510742,-19.63754653930664,-20.195295333862305,-18.661693572998047,-23.166744232177734,-25.767223358154297,-17.47901725769043,-20.107112884521484,-18.87466049194336,-14.021196365356445,-23.9616641998291,-17.631515502929688,-16.309242248535156,-21.137012481689453,-21.122529983520508,-17.305912017822266,-19.604686737060547,-16.410690307617188,-16.7831974029541,-20.05327606201172,-15.291223526000977,-19.566797256469727,-25.432048797607422,-22.283740997314453,-19.412412643432617,-16.233285903930664,-18.915956497192383,-17.18501853942871,-22.00074005126953,-17.94850730895996,-20.63845443725586,-17.973421096801758,-21.913644790649414,-19.405956268310547,-18.921245574951172,-14.960383415222168,-14.140716552734375,-19.379091262817383,-15.164407730102539,-19.23599624633789,-17.085628509521484,-24.900020599365234,-17.930837631225586,-15.017277717590332,-18.39430046081543,-18.29949951171875,-19.81678009033203,-16.499399185180664,-21.1153621673584,-20.64909553527832,-16.530471801757812,-18.152694702148438,-19.830692291259766,-17.068748474121094,-16.368009567260742,-22.440576553344727,-24.575397491455078,-20.936744689941406,-16.465473175048828,-16.289825439453125,-16.341110229492188,-19.04955291748047,-23.555402755737305,-19.5102481842041,-18.35858917236328,-17.890913009643555,-19.442907333374023,-14.255441665649414,-19.23705291748047,-19.83909034729004,-18.734312057495117,-19.848955154418945,-21.674922943115234,-17.039281845092773,-16.802776336669922,-19.45977210998535,-16.507213592529297,-17.979259490966797,-21.164430618286133,-16.55664825439453,-19.571863174438477,-18.527997970581055,-16.438730239868164,-18.222482681274414,-17.97646713256836,-18.645158767700195,-21.904409408569336,-17.995407104492188,-14.85053539276123,-15.628301620483398,-19.503097534179688,-19.802371978759766,-23.55690574645996,-20.865854263305664,-21.97210121154785,-17.619220733642578,-17.55777931213379,-18.90250015258789,-19.595022201538086,-22.55715560913086,-18.7069149017334,-15.946229934692383,-17.116031646728516,-22.056068420410156,-18.132993698120117,-17.69864273071289,-18.772863388061523,-17.69382095336914,-18.974563598632812,-18.597265243530273,-19.086097717285156,-19.763315200805664,-19.784135818481445,-19.49692153930664,-22.22881317138672,-19.871448516845703,-19.91254425048828,-17.67487335205078,-14.83010482788086,-16.431415557861328,-18.875661849975586,-19.289630889892578,-19.932777404785156,-18.83257293701172,-17.950456619262695,-19.316957473754883,-17.2662410736084,-17.319856643676758,-20.356781005859375,-20.86867904663086,-19.766145706176758,-19.172279357910156,-20.614933013916016,-17.56839942932129,-19.70578384399414,-21.004182815551758,-14.180909156799316,-16.228187561035156,-22.096920013427734,-16.230567932128906,-14.014081954956055,-18.133859634399414,-18.271791458129883,-14.894996643066406,-20.85570526123047,-20.33222770690918,-19.34016990661621,-19.300125122070312,-18.69086265563965,-20.986141204833984,-19.05849266052246,-21.730819702148438,-19.53059959411621,-18.280332565307617,-16.290420532226562,-22.174251556396484,-19.60970687866211,-20.317441940307617,-16.59217643737793,-16.612627029418945,-16.287940979003906,-21.55924415588379,-15.447280883789062,-18.48925018310547,-20.813961029052734,-16.740083694458008,-13.458377838134766,-17.664106369018555,-18.019548416137695,-16.611682891845703,-16.419452667236328,-18.20526885986328,-20.381473541259766,-19.548341751098633,-17.654024124145508,-19.76431655883789,-19.859495162963867,-19.523746490478516,-17.158977508544922],"y":[-2.3969573974609375,-5.214266777038574,-3.7279253005981445,-5.133577823638916,-7.954446792602539,-4.154786109924316,-4.240443229675293,-5.181422710418701,-10.927129745483398,-4.262921333312988,-6.06287956237793,-7.911689758300781,-8.279668807983398,-6.503976821899414,-4.634165287017822,-4.3072943687438965,-7.227931022644043,-3.5309109687805176,-6.196506977081299,-7.057223320007324,-4.839535236358643,-6.7767181396484375,-4.782458782196045,-5.173086643218994,-5.148260116577148,-6.474668025970459,-7.045830249786377,-6.8330769538879395,-3.2507665157318115,-5.383304119110107,-5.531240940093994,-4.76724910736084,-4.982306003570557,-2.490175247192383,-8.52447509765625,-5.206350326538086,-4.596973419189453,-8.143037796020508,-7.502743244171143,-3.5996127128601074,-3.1505067348480225,-4.502283573150635,-6.632739067077637,-9.811294555664062,-5.566807746887207,0.21051645278930664,-5.429094314575195,-6.422101974487305,-4.654585838317871,-8.110465049743652,-6.150576591491699,-3.421238899230957,-5.653045654296875,-2.7180838584899902,-5.567200660705566,-2.385591745376587,-6.469362735748291,-7.134333610534668,-3.8116707801818848,-2.9478046894073486,-3.6082770824432373,-2.0353798866271973,-6.554582118988037,-6.126589298248291,-4.457681655883789,-7.735702037811279,-6.4336652755737305,-3.826637029647827,-4.8177995681762695,-5.481667995452881,-2.022432804107666,-5.711475372314453,-4.03279972076416,-4.492038726806641,-5.628598690032959,-5.989644527435303,-4.80182409286499,-7.26497220993042,-4.882323741912842,-9.12441349029541,-10.606302261352539,-10.485782623291016,-0.8920001983642578,-3.1166493892669678,-3.0256154537200928,-3.9742465019226074,-1.1344647407531738,-5.613372325897217,-4.215630531311035,-7.389276027679443,-5.666075706481934,-4.759469032287598,-6.192016124725342,-7.459195137023926,-6.032945156097412,-7.9882917404174805,-8.4464750289917,-1.4298222064971924,-9.233048439025879,-5.813747406005859,-5.003689289093018,-8.137388229370117,-1.3100647926330566,-4.294522285461426,-7.8950042724609375,-5.845222473144531,-6.456150531768799,-3.571714162826538,-3.465217351913452,-7.576606750488281,-7.941859722137451,-7.9267578125,-2.738215446472168,-7.211066246032715,-8.11870288848877,-2.5428354740142822,-4.6299591064453125,-4.474435329437256,-7.748103141784668,-3.999894380569458,-4.772665023803711,-2.7248823642730713,-3.324282169342041,-5.149034023284912,-4.672659873962402,-6.693130970001221,-6.42601203918457,-4.699822425842285,-4.755293369293213,-2.920365333557129,-6.160664081573486,-6.425868988037109,-5.939734935760498,-4.669125556945801,-8.558124542236328,-4.80165958404541,-3.0789270401000977,-7.423728942871094,-2.919304847717285,-4.314515113830566,-7.103615760803223,-5.563617706298828,-5.130669116973877,-3.886960983276367,-5.658827304840088,-2.074631929397583,-8.062849044799805,-4.561659812927246,-5.2123703956604,-9.177393913269043,-7.345808982849121,-4.722843170166016,-5.1300554275512695,-5.713542938232422,-4.4308013916015625,-1.9684438705444336,-5.272624492645264,-4.392658233642578,-2.037222385406494,-3.7481110095977783,-6.141972541809082,-6.589566230773926,-1.4112775325775146,-9.049758911132812,-0.9059820175170898,-1.815622329711914,-5.663717746734619,-5.770271301269531,-3.8802967071533203,-2.4721872806549072,-5.936341285705566,-7.051857948303223,-7.748922348022461,-8.779422760009766,-3.8221278190612793,-6.609267234802246,-3.0047450065612793,-6.027502536773682,-8.118816375732422,-0.23999309539794922,-4.416080474853516,-5.321953773498535,-2.7318549156188965,-8.876153945922852,-5.170572757720947,-1.0753898620605469,-8.6068754196167,-8.806008338928223,-6.514641284942627,-2.215498208999634,-3.193490743637085,-8.439168930053711,-5.505091667175293,-5.90566349029541,-10.204246520996094,-10.409587860107422,-6.8577423095703125,-8.250965118408203,-6.162041664123535,-3.470362663269043,-7.286647796630859,-6.410272121429443,-2.375833511352539,-5.4492292404174805,-7.176997184753418,-4.877683639526367,-5.28444766998291,-2.688476085662842,-11.127910614013672,-5.079733371734619,-9.942243576049805,-7.3994622230529785,-8.077275276184082,-4.414538383483887,-3.9022226333618164,-7.871356010437012,-7.247000217437744,-8.342279434204102,-4.595988750457764,-5.199789524078369,-8.019502639770508,-3.0294201374053955,-3.865248203277588,-3.898468494415283,-5.666804790496826,-6.5538434982299805,-4.7859978675842285,-8.306976318359375,-6.357185363769531,-4.269003868103027,-9.042267799377441,-7.718050003051758,-1.6582770347595215,-4.802417278289795,-6.186646938323975,-4.6856207847595215,-3.0495071411132812,-3.0682084560394287,-5.351725101470947,-1.2499127388000488,-5.647239685058594,-7.942544937133789,-7.714549541473389,-6.005688667297363,-3.5182600021362305,-6.56343412399292,-5.9607768058776855,-4.110055446624756,-9.01270866394043,-4.357668876647949],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-18.706689834594727],"y":[-5.245700836181641],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-18.706689834594727],"y":[-5.245700836181641],"type":"scatter"},{"marker":{"color":"#AB63FA","size":3},"mode":"markers","name":"cluster 3","x":[-18.729272842407227,-24.88858985900879,-18.64059829711914,-18.413198471069336,-18.374177932739258,-18.505847930908203,-19.891908645629883,-22.0452880859375,-20.556293487548828,-18.595888137817383,-20.344011306762695,-21.697858810424805,-21.757383346557617,-20.508575439453125,-18.754793167114258,-19.411968231201172,-21.291976928710938,-18.353534698486328,-17.019773483276367,-20.8243350982666,-18.935556411743164,-21.778043746948242,-24.391347885131836,-23.95330810546875,-21.651525497436523,-18.996265411376953,-18.756961822509766,-23.71198081970215,-22.407922744750977,-23.208194732666016,-16.234853744506836,-19.168468475341797,-21.705774307250977,-23.201398849487305,-19.069183349609375,-21.764680862426758,-21.840267181396484,-22.70935821533203,-16.014610290527344,-23.931764602661133,-22.415586471557617,-22.329017639160156,-22.421037673950195,-21.41786003112793,-18.979082107543945,-19.46440887451172,-20.092456817626953,-19.429697036743164,-18.220531463623047,-20.202775955200195,-19.57779312133789,-23.03131866455078,-17.35670280456543,-21.759315490722656,-23.992143630981445,-20.300275802612305,-21.190170288085938,-23.700321197509766,-22.245372772216797,-18.73027992248535,-21.826189041137695,-21.07071304321289,-24.615036010742188,-22.225109100341797,-22.505956649780273,-20.096982955932617,-19.68341827392578,-23.505104064941406,-23.380332946777344,-22.11959457397461,-17.559188842773438,-21.335073471069336,-16.41758155822754,-19.925884246826172,-23.17928123474121,-19.988740921020508,-24.94684410095215,-19.21650505065918,-21.072437286376953,-20.11487579345703,-20.55824089050293,-20.83823585510254,-17.910905838012695,-19.432170867919922,-19.212514877319336,-17.892316818237305,-22.75382423400879,-25.439556121826172,-25.868898391723633,-23.334980010986328,-16.827863693237305,-18.551145553588867,-22.83521842956543,-19.79706573486328,-20.605966567993164,-20.14571189880371,-21.11846923828125,-23.45189666748047,-22.795331954956055,-23.985027313232422,-21.425146102905273,-21.54134750366211,-17.744985580444336,-17.907377243041992,-21.410987854003906,-18.001663208007812,-19.29987144470215,-22.473468780517578,-20.6120548248291,-20.8223934173584,-21.351789474487305,-15.291061401367188,-20.073551177978516,-23.027746200561523,-20.801816940307617,-20.974336624145508,-23.74662208557129,-21.07016372680664,-19.646146774291992,-21.77552032470703,-20.55347442626953,-19.573871612548828,-18.74039077758789,-17.235218048095703,-22.762815475463867,-19.736282348632812,-18.439226150512695,-22.353137969970703,-23.04098892211914,-18.195077896118164,-19.02056121826172,-19.421615600585938,-23.17959213256836,-19.72751235961914,-24.915924072265625,-19.04086685180664,-24.040666580200195,-20.78937530517578,-19.696317672729492,-20.56715965270996,-21.493019104003906,-22.870872497558594,-18.57164192199707,-20.15166473388672,-18.246288299560547,-15.859151840209961,-19.36421012878418,-20.85653305053711,-22.568275451660156,-19.46269416809082,-14.867942810058594,-20.032188415527344,-19.423730850219727,-23.67829704284668,-21.758785247802734,-16.49230194091797,-23.242874145507812,-21.363649368286133,-19.688232421875,-20.075702667236328,-17.748083114624023,-24.18648910522461,-21.707143783569336,-21.320159912109375,-17.836864471435547,-17.53141975402832,-21.578319549560547,-20.090633392333984,-20.899505615234375,-18.848493576049805,-17.17682456970215,-16.21945571899414,-20.710784912109375,-20.37027931213379,-21.095703125,-19.30573272705078,-18.38981819152832,-18.01462173461914,-24.713165283203125,-20.336397171020508,-18.971946716308594,-19.163972854614258,-19.050588607788086,-21.464078903198242,-21.02102279663086,-21.291685104370117,-22.44430160522461,-21.53601837158203,-21.204395294189453,-21.5570011138916,-21.44476890563965,-20.0882568359375,-18.00638198852539,-18.535236358642578,-18.446605682373047,-20.269615173339844,-22.878780364990234,-15.65955638885498,-22.376678466796875,-18.848424911499023,-20.131925582885742,-18.160932540893555,-21.390716552734375,-21.650684356689453,-21.198638916015625,-21.31653594970703,-19.702392578125,-19.534780502319336,-20.976078033447266,-19.479501724243164,-20.13414764404297,-21.86914825439453,-20.0261287689209,-18.784252166748047,-21.113170623779297,-22.704227447509766,-22.278682708740234,-21.06428337097168,-19.73459243774414,-20.478425979614258,-17.266408920288086,-19.435848236083984,-21.369775772094727,-26.125139236450195,-20.925209045410156,-22.034812927246094,-21.304412841796875,-21.861122131347656,-23.065427780151367,-20.346084594726562,-22.81110382080078,-17.335805892944336,-23.915180206298828,-16.913217544555664,-19.844804763793945,-20.419239044189453,-19.4638614654541,-21.124507904052734,-22.996273040771484,-19.658864974975586,-19.083112716674805,-21.826946258544922,-23.277687072753906,-21.13001251220703,-19.31300926208496,-24.088336944580078,-20.70524787902832,-17.94198226928711,-20.78548812866211,-22.760005950927734],"y":[5.096549034118652,7.049332618713379,8.909868240356445,8.016861915588379,11.878761291503906,5.292832374572754,11.711738586425781,8.450275421142578,9.35278034210205,10.393760681152344,10.485952377319336,9.746909141540527,5.429883003234863,8.212258338928223,8.327034950256348,6.187065124511719,4.024733066558838,6.558775901794434,9.063727378845215,8.359020233154297,8.75679874420166,6.895076274871826,6.845462322235107,12.195286750793457,5.006462097167969,7.760155200958252,10.39736557006836,8.46862506866455,9.177868843078613,5.559926986694336,5.79826545715332,7.332425117492676,8.963004112243652,11.87835693359375,12.975247383117676,7.837119102478027,9.866868019104004,11.547372817993164,8.017817497253418,5.493055820465088,9.434844970703125,7.131298542022705,8.015789985656738,10.334327697753906,9.242546081542969,9.196064949035645,11.904093742370605,8.084083557128906,9.587491989135742,10.134839057922363,10.11209487915039,10.894148826599121,12.1345853805542,8.121794700622559,11.4876070022583,10.020998001098633,10.269813537597656,9.597220420837402,6.221399784088135,7.124667167663574,8.715788841247559,8.94090747833252,12.966087341308594,6.627581596374512,11.949153900146484,11.761159896850586,8.439935684204102,8.207571029663086,9.331663131713867,4.251867771148682,6.80094051361084,10.509637832641602,9.417344093322754,9.135666847229004,7.864975929260254,9.490754127502441,11.681961059570312,9.47964096069336,10.242722511291504,10.19731330871582,11.71674919128418,11.744352340698242,11.931480407714844,6.863741874694824,7.533560276031494,13.46342658996582,8.058914184570312,11.127206802368164,5.356972694396973,6.318399429321289,10.66460132598877,12.081207275390625,9.73035717010498,8.702710151672363,8.351639747619629,11.586249351501465,10.585389137268066,9.031097412109375,9.409920692443848,6.520334720611572,7.00762939453125,10.666272163391113,8.969433784484863,9.457207679748535,10.51980972290039,8.959444999694824,6.767205715179443,13.918760299682617,9.046497344970703,5.932514190673828,7.631134510040283,5.709893226623535,9.17736530303955,8.231557846069336,8.079914093017578,11.262250900268555,12.116363525390625,11.351715087890625,7.674842834472656,8.281057357788086,4.5055012702941895,9.775300979614258,14.38041877746582,10.271953582763672,8.96696949005127,11.8857421875,5.7546586990356445,10.225417137145996,8.714073181152344,7.268218994140625,11.230411529541016,7.313052177429199,3.031282901763916,5.163022994995117,12.201239585876465,13.800617218017578,10.899879455566406,9.161162376403809,8.372276306152344,7.217512130737305,9.620133399963379,8.908669471740723,10.88524055480957,12.034449577331543,5.249270439147949,9.776113510131836,10.915929794311523,5.208134651184082,11.109614372253418,8.170943260192871,11.02932357788086,9.32793140411377,5.72052001953125,11.451211929321289,9.364191055297852,11.402604103088379,8.76901626586914,9.361724853515625,11.086835861206055,7.077607154846191,10.700394630432129,12.442825317382812,11.660688400268555,11.688695907592773,3.971463680267334,6.599224090576172,4.920380592346191,10.813061714172363,9.158056259155273,14.124112129211426,6.814990997314453,9.997678756713867,8.436666488647461,10.790520668029785,10.780747413635254,8.582186698913574,9.043107986450195,6.507101058959961,6.132073402404785,11.57738208770752,5.356683731079102,11.510821342468262,7.326781749725342,12.072057723999023,12.863377571105957,8.467535018920898,9.515034675598145,6.873392581939697,7.601968765258789,8.211631774902344,11.103023529052734,10.366954803466797,5.652336120605469,10.336225509643555,8.973592758178711,13.055793762207031,7.338960647583008,7.98708963394165,11.945371627807617,7.605190277099609,9.705709457397461,8.53051471710205,10.059309959411621,7.766096115112305,11.520325660705566,7.021236419677734,7.560451507568359,11.657268524169922,7.911218643188477,5.617547035217285,5.295555591583252,11.085981369018555,10.720305442810059,9.34136962890625,4.919278621673584,11.363151550292969,10.639009475708008,8.66079044342041,9.32776165008545,10.172809600830078,7.683245658874512,7.423390865325928,6.8807573318481445,7.6763410568237305,10.052191734313965,11.467228889465332,10.850114822387695,7.137287616729736,9.252175331115723,10.280884742736816,6.581130504608154,10.401117324829102,7.28129768371582,7.916652202606201,7.520597457885742,6.786144733428955,9.126370429992676,9.697312355041504,11.109733581542969,9.886630058288574,10.103628158569336,6.572298049926758,10.833246231079102,9.192835807800293,9.98744010925293,8.315469741821289,14.385078430175781,9.559182167053223,9.79703426361084,5.094233512878418],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-20.503978729248047],"y":[9.081546783447266],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-20.503978729248047],"y":[9.081546783447266],"type":"scatter"},{"marker":{"color":"#FFA15A","size":3},"mode":"markers","name":"cluster 4","x":[-8.600279808044434,-12.10361099243164,-12.14765453338623,-10.046884536743164,-9.201055526733398,-12.007455825805664,-4.321677207946777,-9.431857109069824,-10.79393482208252,-6.351062774658203,-13.856291770935059,-7.982555389404297,-10.778120040893555,-8.85059642791748,-10.491353988647461,-12.326152801513672,-7.175271034240723,-12.458988189697266,-13.064464569091797,-8.235206604003906,-10.59919261932373,-10.732748985290527,-8.94236946105957,-11.100624084472656,-8.151305198669434,-10.83580493927002,-14.114583969116211,-15.892695426940918,-9.881904602050781,-7.548067569732666,-4.985658645629883,-10.445358276367188,-8.225241661071777,-9.147982597351074,-9.012353897094727,-11.588910102844238,-7.2593278884887695,-11.601536750793457,-6.767746448516846,-5.009767055511475,-9.238189697265625,-8.618598937988281,-8.557352066040039,-12.621267318725586,-3.0511579513549805,-11.206414222717285,-8.510185241699219,-8.308615684509277,-10.656183242797852,-13.170201301574707,-10.527009963989258,-7.221179962158203,-13.217294692993164,-12.291364669799805,-8.308812141418457,-8.062202453613281,-10.889323234558105,-8.394033432006836,-8.980734825134277,-8.061798095703125,-13.327995300292969,-10.457670211791992,-10.561936378479004,-12.205080032348633,-10.206729888916016,-8.429023742675781,-12.737086296081543,-12.429974555969238,-7.56069278717041,-7.186188220977783,-9.949129104614258,-10.87218952178955,-7.743781089782715,-8.065786361694336,-6.115677833557129,-8.89757251739502,-9.982120513916016,-12.49746322631836,-16.871959686279297,-8.77431869506836,-8.683637619018555,-9.584238052368164,-8.260108947753906,-8.443947792053223,-9.918534278869629,-15.030573844909668,-16.7659854888916,-8.954389572143555,-12.082758903503418,-8.7927885055542,-9.204771995544434,-12.315057754516602,-10.611921310424805,-11.762124061584473,-9.83623218536377,-7.875572681427002,-6.840780258178711,-7.849913597106934,-7.030721664428711,-9.261911392211914,-11.061655044555664,-12.751651763916016,-9.53978157043457,-5.955102920532227,-10.475480079650879,-7.575878620147705,-5.290384292602539,-7.4312214851379395,-7.686669826507568,-9.265477180480957,-13.562292098999023,-8.067757606506348,-5.928615570068359,-11.14254379272461,-8.080652236938477,-9.174582481384277,-7.377906322479248,-11.867603302001953,-11.04150390625,-11.337408065795898,-10.274253845214844,-10.290769577026367,-8.61528491973877,-9.00598430633545,-11.66600227355957,-10.86557388305664,-10.07654857635498,-10.761791229248047,-9.196762084960938,-9.305646896362305,-13.401457786560059,-7.413378715515137,-12.233810424804688,-9.582377433776855,-11.749908447265625,-8.927349090576172,-8.558415412902832,-8.25199031829834,-13.6466064453125,-10.634471893310547,-9.64920425415039,-10.344839096069336,-9.502182960510254,-5.956055641174316,-10.455148696899414,-11.436091423034668,-7.366311550140381,-11.716115951538086,-11.457780838012695,-10.119546890258789,-6.487796783447266,-7.513344764709473,-9.137932777404785,-7.262057304382324,-8.414298057556152,-5.233402252197266,-9.272754669189453,-11.125605583190918,-9.548826217651367,-7.108059883117676,-8.809890747070312,-8.030457496643066,-6.981706619262695,-7.377267837524414,-13.087952613830566,-12.000344276428223,-7.6092143058776855,-6.271859169006348,-11.963719367980957,-11.865251541137695,-8.496370315551758,-10.722675323486328,-11.15896224975586,-10.42664909362793,-7.754755020141602,-9.915626525878906,-5.2764506340026855,-6.334891319274902,-11.313973426818848,-9.33447551727295,-8.676901817321777,-9.793972969055176,-10.022170066833496,-10.224037170410156,-13.395475387573242,-9.864212989807129,-8.716399192810059,-12.381062507629395,-10.413830757141113,-8.467181205749512,-10.35099983215332,-9.567347526550293,-7.6334028244018555,-10.392940521240234,-8.574857711791992,-9.930715560913086,-5.490166187286377,-8.06926155090332,-13.222980499267578,-7.483623504638672,-7.177618503570557,-5.924283504486084,-7.777842044830322,-9.45787525177002,-7.4070916175842285,-10.088786125183105,-7.039541244506836,-8.80671501159668,-11.783917427062988,-12.611946105957031,-10.853357315063477,-10.662331581115723,-9.261443138122559,-9.977265357971191,-8.961291313171387,-11.526904106140137,-8.45202350616455,-10.37489128112793,-11.229190826416016,-8.945115089416504,-6.900306701660156,-10.512042045593262,-9.616333961486816,-8.230165481567383,-10.43157958984375,-10.326397895812988,-10.076836585998535,-7.697328567504883,-11.054885864257812,-10.01740837097168,-8.35953426361084,-9.028426170349121,-11.740781784057617,-4.273074150085449,-8.872232437133789,-11.219478607177734,-8.559585571289062,-12.894989013671875,-7.532517433166504,-13.100044250488281,-12.649214744567871,-8.306160926818848,-9.870658874511719,-12.515071868896484,-11.063370704650879,-8.09744930267334,-10.042791366577148,-9.475582122802734,-8.004166603088379,-11.936446189880371],"y":[22.743539810180664,24.16919708251953,25.0251522064209,25.900161743164062,21.587554931640625,27.705617904663086,22.87245750427246,23.84690284729004,26.228200912475586,26.56268882751465,26.676258087158203,24.73517417907715,22.20035171508789,24.58065414428711,24.359962463378906,23.589523315429688,27.81822395324707,25.484554290771484,19.327228546142578,25.916807174682617,23.770801544189453,25.56364631652832,24.70351219177246,24.93872833251953,26.459369659423828,25.316364288330078,23.77635955810547,25.07883071899414,26.171701431274414,21.918712615966797,29.12619400024414,24.513723373413086,24.666683197021484,24.338821411132812,21.454212188720703,26.5505428314209,24.956356048583984,23.688236236572266,21.330934524536133,26.833581924438477,21.04785919189453,20.765419006347656,25.685670852661133,24.009382247924805,23.75845718383789,23.716167449951172,28.249034881591797,22.57678985595703,22.686904907226562,26.835844039916992,24.586780548095703,27.812076568603516,20.40938949584961,25.60614776611328,25.73059844970703,20.56486701965332,27.198835372924805,22.551227569580078,25.341751098632812,27.61357879638672,24.30692481994629,27.246902465820312,24.91140365600586,25.521657943725586,22.463455200195312,23.387331008911133,27.042726516723633,23.952205657958984,21.033626556396484,24.695608139038086,28.345739364624023,28.65167808532715,24.607709884643555,27.15869140625,19.741249084472656,20.403369903564453,24.210575103759766,21.159879684448242,22.881038665771484,23.043725967407227,29.53091049194336,25.655502319335938,24.503196716308594,22.72159194946289,22.88680648803711,22.943166732788086,22.309293746948242,27.977127075195312,20.06553077697754,21.433673858642578,26.399377822875977,27.173858642578125,23.00019645690918,26.4375,24.56438446044922,26.510116577148438,22.590972900390625,25.35338592529297,22.346416473388672,25.729711532592773,27.625680923461914,24.76819610595703,23.339092254638672,22.508962631225586,26.104509353637695,18.556913375854492,21.60326385498047,23.777915954589844,24.75299072265625,23.586885452270508,23.766780853271484,25.76375389099121,25.026580810546875,23.963171005249023,26.039113998413086,25.007930755615234,21.547443389892578,24.845178604125977,19.799287796020508,22.864486694335938,25.367431640625,21.888858795166016,26.019668579101562,26.340641021728516,26.414987564086914,23.600156784057617,23.249401092529297,21.754350662231445,19.290672302246094,22.180116653442383,22.14286231994629,26.186405181884766,24.70608901977539,20.765579223632812,27.23318099975586,26.097997665405273,25.306915283203125,23.472421646118164,22.085763931274414,24.30583381652832,24.30274772644043,26.464616775512695,22.98529815673828,23.500106811523438,24.952001571655273,19.976205825805664,27.301612854003906,27.78390121459961,25.43518829345703,30.547283172607422,26.988052368164062,25.167970657348633,21.528928756713867,26.957048416137695,27.557361602783203,25.07265853881836,29.167701721191406,23.4927921295166,25.415115356445312,31.278610229492188,24.98404312133789,20.786903381347656,23.170167922973633,27.227550506591797,25.437793731689453,23.345245361328125,22.90399932861328,23.42783546447754,23.50377082824707,26.9918270111084,24.77071189880371,25.441221237182617,24.401439666748047,24.686203002929688,25.075077056884766,24.92303466796875,23.291086196899414,28.618661880493164,23.902851104736328,26.73432731628418,25.146568298339844,20.78064727783203,29.728137969970703,26.393272399902344,24.7730770111084,30.030563354492188,25.843280792236328,26.564905166625977,25.74042320251465,24.072341918945312,25.759166717529297,26.125762939453125,21.94133758544922,28.726428985595703,25.29500961303711,26.347553253173828,24.46858024597168,28.195083618164062,26.804384231567383,26.84978485107422,21.87255859375,26.37096405029297,24.822145462036133,23.825620651245117,27.145034790039062,25.85413360595703,23.588455200195312,22.668773651123047,24.970367431640625,23.74470329284668,20.167156219482422,25.82902717590332,25.372390747070312,22.63360023498535,23.490890502929688,21.594806671142578,22.37969970703125,26.184295654296875,25.686594009399414,22.98983383178711,23.646930694580078,23.441328048706055,23.168001174926758,26.658031463623047,22.780366897583008,23.858501434326172,19.736209869384766,24.620849609375,23.79120445251465,25.055328369140625,22.651716232299805,21.001781463623047,25.409400939941406,23.543569564819336,26.66622543334961,25.790470123291016,23.636865615844727,24.80181121826172,26.678241729736328,26.70738983154297,22.609853744506836,23.78322982788086,26.075313568115234,24.01766014099121,21.864561080932617,23.54413604736328,22.094404220581055,22.38316535949707,22.771831512451172,22.056541442871094],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-9.42786979675293],"y":[24.588783264160156],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-9.42786979675293],"y":[24.588783264160156],"type":"scatter"},{"marker":{"color":"#19D3F3","size":3},"mode":"markers","name":"cluster 5","x":[24.899200439453125,25.795066833496094,26.070402145385742,25.927711486816406,26.66252899169922,22.774890899658203,20.685461044311523,21.782752990722656,25.928184509277344,27.272686004638672,23.010082244873047,26.111072540283203,26.106101989746094,22.6607666015625,22.559585571289062,24.500028610229492,23.088863372802734,23.79488754272461,27.761085510253906,22.000965118408203,20.82413673400879,24.476594924926758,28.03115463256836,27.3532657623291,28.165542602539062,28.796466827392578,23.99007797241211,22.056968688964844,23.61009407043457,22.30701446533203,25.089183807373047,22.002492904663086,27.367473602294922,27.246871948242188,25.25930404663086,24.001001358032227,26.041330337524414,21.625625610351562,24.981874465942383,23.788532257080078,26.80269432067871,23.07561492919922,26.795101165771484,24.452314376831055,29.16944122314453,28.070024490356445,25.093839645385742,23.33034324645996,26.194318771362305,25.2665958404541,27.562015533447266,23.78020668029785,22.557395935058594,24.393325805664062,26.101490020751953,27.476511001586914,26.19685173034668,24.111099243164062,20.387060165405273,21.006633758544922,25.167192459106445,24.56340217590332,23.051406860351562,28.906593322753906,22.50932502746582,24.768089294433594,22.605987548828125,25.35858726501465,26.448427200317383,26.76077651977539,23.56056022644043,22.99807357788086,24.739856719970703,26.94286346435547,27.658893585205078,28.522022247314453,24.90033721923828,24.275232315063477,24.430240631103516,23.79802894592285,21.747955322265625,28.819225311279297,28.93037986755371,22.716203689575195,27.45506477355957,25.689197540283203,23.958393096923828,24.086822509765625,23.32016372680664,27.350196838378906,27.395076751708984,23.01870346069336,22.400943756103516,23.701095581054688,24.106212615966797,21.438077926635742,20.169567108154297,20.630939483642578,23.41472625732422,24.9272403717041,24.787208557128906,21.720869064331055,28.558868408203125,23.521160125732422,25.13656234741211,23.13912010192871,24.775182723999023,27.638830184936523,23.014812469482422,23.67927360534668,27.79462242126465,25.149608612060547,27.190338134765625,26.91124153137207,26.07159996032715,25.266294479370117,25.313432693481445,21.610538482666016,22.321277618408203,21.79326629638672,22.2254695892334,24.561670303344727,25.729812622070312,26.55601692199707,24.761499404907227,24.55518913269043,24.577787399291992,26.31360626220703,25.303955078125,25.912071228027344,27.739866256713867,24.32675552368164,25.038087844848633,19.75543212890625,21.228845596313477,24.750078201293945,23.23501205444336,25.63028907775879,25.343130111694336,26.138517379760742,30.377342224121094,26.338308334350586,26.775650024414062,22.673259735107422,25.929698944091797,29.010038375854492,25.570688247680664,25.132904052734375,27.413604736328125,29.301029205322266,25.478466033935547,26.593420028686523,22.96202278137207,25.76799964904785,26.01138687133789,26.33232879638672,23.242515563964844,25.34132194519043,26.167449951171875,24.88158416748047,27.094654083251953,24.65334129333496,22.707387924194336,27.433595657348633,25.31332778930664,21.087751388549805,26.470483779907227,25.602558135986328,27.10983657836914,28.32958221435547,23.908601760864258,23.664609909057617,26.397850036621094,22.413204193115234,23.011751174926758,24.718311309814453,21.313535690307617,26.970869064331055,26.773643493652344,26.911699295043945,22.799867630004883,24.324865341186523,24.34576988220215,29.44414710998535,25.120370864868164,26.551300048828125,21.735029220581055,22.63677215576172,30.06561851501465,22.052459716796875,25.390186309814453,26.734445571899414,28.65050506591797,25.38561248779297,23.859962463378906,25.764934539794922,26.86248016357422,18.875762939453125,22.709156036376953,22.840129852294922,26.62228012084961,26.380624771118164,24.820100784301758,22.772153854370117,23.607648849487305,23.137004852294922,23.466947555541992,26.885786056518555,21.741676330566406,24.945688247680664,20.279239654541016,25.78778648376465,23.788789749145508,25.024147033691406,25.714275360107422,25.204206466674805,27.750133514404297,20.70173454284668,23.45760726928711,21.71678924560547,27.44124984741211,26.1024169921875,26.064228057861328,24.952377319335938,27.116870880126953,24.09061622619629,29.515384674072266,24.216279983520508,27.689786911010742,27.697851181030273,24.166229248046875,26.182010650634766,21.880571365356445,21.240501403808594,21.066574096679688,27.122303009033203,30.856689453125,22.78137969970703,21.850536346435547,28.399690628051758,23.485631942749023,23.780628204345703,24.41297721862793,28.078693389892578,22.81817626953125,27.078792572021484,20.8679141998291,25.927005767822266,18.548526763916016,24.61690902709961],"y":[3.0319652557373047,8.647820472717285,6.485493183135986,1.8997925519943237,3.5212600231170654,3.314321517944336,3.829113006591797,3.3844125270843506,3.3686046600341797,3.3728227615356445,5.074520587921143,4.550687313079834,3.8484814167022705,2.5673584938049316,9.531397819519043,6.765503883361816,2.8073198795318604,2.4185447692871094,3.6773929595947266,4.295487880706787,2.736370325088501,-0.0961298942565918,2.406905174255371,6.3580522537231445,0.991213321685791,-0.7861075401306152,1.4198143482208252,5.442190647125244,7.63036584854126,1.4205143451690674,4.413945198059082,2.7077383995056152,2.3210105895996094,1.003706455230713,10.02442741394043,-0.8038420677185059,3.422079563140869,4.378314971923828,6.837148666381836,2.6777665615081787,1.8096380233764648,1.2987620830535889,3.622450590133667,2.6359856128692627,6.171802043914795,2.058090925216675,2.671121120452881,2.8334083557128906,4.475510597229004,5.703097820281982,0.796891450881958,4.104783535003662,4.727367401123047,5.064334869384766,3.8951079845428467,4.735243797302246,4.412771701812744,2.0145936012268066,3.5332276821136475,4.008615493774414,9.188220977783203,6.305426597595215,7.566341400146484,6.576202392578125,2.737177610397339,3.6308414936065674,0.6281270980834961,-0.3846395015716553,2.829456090927124,0.036376237869262695,0.6173522472381592,6.221410751342773,5.293233394622803,-1.6498050689697266,1.2223827838897705,1.4708499908447266,2.320496082305908,4.194249629974365,0.6742973327636719,3.8986411094665527,0.1791210174560547,6.081787109375,3.613588809967041,4.302425384521484,2.477876663208008,0.8180911540985107,0.9963235855102539,5.189098834991455,3.562598466873169,7.5441741943359375,4.140510559082031,4.069432735443115,1.1441268920898438,7.160279750823975,4.499896049499512,3.7693867683410645,2.7258567810058594,-0.020596027374267578,4.309000492095947,4.1401519775390625,3.2280688285827637,2.297950267791748,4.5032758712768555,2.8498289585113525,4.085575103759766,7.201923847198486,0.19002175331115723,3.149397611618042,6.872982501983643,0.52272629737854,1.2807166576385498,0.24246501922607422,6.1160664558410645,7.34480094909668,3.399052619934082,5.754234313964844,3.4950406551361084,6.491581916809082,1.3663392066955566,4.147449493408203,4.641958236694336,3.4370739459991455,5.821699619293213,4.045271396636963,2.6516013145446777,4.902143478393555,6.256364822387695,1.9593440294265747,3.167280912399292,-1.6063990592956543,5.547329425811768,4.550471305847168,4.454911231994629,5.346568584442139,3.5084757804870605,-1.9007582664489746,5.555176734924316,4.541838645935059,2.1302638053894043,0.34851932525634766,5.442819118499756,1.049978256225586,-0.21614313125610352,6.830776691436768,2.053988456726074,4.782634258270264,4.4563307762146,7.711938381195068,4.437340259552002,6.186797142028809,2.606409788131714,5.1933465003967285,2.736240863800049,2.1264495849609375,4.2367048263549805,4.338527202606201,4.100940227508545,2.102409601211548,2.6901164054870605,4.439950942993164,3.992133855819702,2.9450674057006836,-1.1087837219238281,3.4456934928894043,2.4532310962677,5.001343250274658,6.772556304931641,-0.2407207489013672,3.6043174266815186,1.4624583721160889,4.777252197265625,4.330015182495117,5.162171840667725,4.42834997177124,7.357789516448975,3.4248228073120117,4.829172134399414,1.725600004196167,5.5704498291015625,5.258073806762695,5.728021621704102,2.576655387878418,1.6610521078109741,5.290985107421875,3.347531318664551,2.8020577430725098,2.438289165496826,11.590871810913086,1.5982846021652222,2.8910014629364014,2.6942076683044434,4.0157012939453125,5.752374172210693,8.181634902954102,0.5997436046600342,1.0372247695922852,3.3782434463500977,5.93861198425293,6.664712905883789,2.9290497303009033,1.2016079425811768,3.935314416885376,2.354177951812744,3.358090400695801,3.8846640586853027,5.460848808288574,1.9229050874710083,4.288052082061768,5.118373394012451,-0.012981891632080078,5.313022613525391,3.4747748374938965,3.0935518741607666,2.2727110385894775,0.42185163497924805,0.9570767879486084,8.854612350463867,5.225698471069336,1.8014941215515137,6.131137847900391,3.9671125411987305,3.7078397274017334,3.9244353771209717,4.110875606536865,4.773287773132324,2.424561023712158,8.203197479248047,4.173276424407959,6.354229927062988,5.656614303588867,2.390371322631836,0.4597814083099365,4.4864912033081055,5.405448913574219,2.6318740844726562,7.523460865020752,7.182490348815918,7.595928192138672,6.12595272064209,1.4430482387542725,2.580331563949585,5.483197212219238,3.344271421432495,3.2679390907287598,5.319302558898926,3.822760581970215,4.575725078582764,6.597330093383789,3.4107120037078857,8.484992027282715],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[24.846019744873047],"y":[3.5654640197753906],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[24.846019744873047],"y":[3.5654640197753906],"type":"scatter"}],                        {"template":{"data":{"scatter":[{"marker":{"color":"#d92310"},"type":"scatter"}]},"layout":{"height":576,"paper_bgcolor":"#fcfcfc","plot_bgcolor":"#fcfcfc","width":1024}},"xaxis":{"zeroline":false},"yaxis":{"zeroline":false}},                        {"responsive": true}                    ).then(function(){
                            
var gd = document.getElementById('dd6952c5-750c-4916-bf52-aaff6ab58e62');
var x = new MutationObserver(function (mutations, observer) {{
        var display = window.getComputedStyle(gd).display;
        if (!display || display === 'none') {{
            console.log([gd, 'removed!']);
            Plotly.purge(gd);
            observer.disconnect();
        }}
}});

// Listen for the removal of the full notebook cells
var notebookContainer = gd.closest('#notebook-container');
if (notebookContainer) {{
    x.observe(notebookContainer, {childList: true});
}}

// Listen for the clearing of the current output cell
var outputEl = gd.closest('.output');
if (outputEl) {{
    x.observe(outputEl, {childList: true});
}}

                        })                };                });            </script>        </div>
</div>
</div>
<p>In the end, all clusters will converge at their respective center (marked by X).</p>
<section id="implementation" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="implementation">Implementation</h2>
<p>Let’s start off simple and apply the algorithm to a single point.</p>
<section id="calculate-distances" class="level3">
<h3 class="anchored" data-anchor-id="calculate-distances">Calculate Distances</h3>
<blockquote class="blockquote">
<p>For each data point <img src="https://latex.codecogs.com/png.latex?x"> in the dataset, calculate the distance between <img src="https://latex.codecogs.com/png.latex?x"> and every other data point in the dataset.</p>
</blockquote>
<div id="8a698e0f" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1">data</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="14">
<pre><code>tensor([[  0.611, -20.199],
        [  4.455, -24.188],
        [  2.071, -20.446],
        ...,
        [ 25.927,   6.597],
        [ 18.549,   3.411],
        [ 24.617,   8.485]])</code></pre>
</div>
</div>
<div id="91a3c528" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1">X <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> data.clone()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> X.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="15">
<pre><code>torch.Size([1500, 2])</code></pre>
</div>
</div>
<p>Each point has an <img src="https://latex.codecogs.com/png.latex?x"> coordinate and a <img src="https://latex.codecogs.com/png.latex?y"> coordinate.</p>
<div id="b8309bfa" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> X[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, :]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> X</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="16">
<pre><code>tensor([[  0.000,   0.000],
        [ -3.844,   3.989],
        [ -1.460,   0.247],
        ...,
        [-25.316, -26.796],
        [-17.938, -23.610],
        [-24.006, -28.684]])</code></pre>
</div>
</div>
<p>The distance metric we’ll use is <a href="https://www.mathsisfun.com/algebra/distance-2-points.html">Euclidean distance</a> —&nbsp;also better known as Pythagoras’ theorem.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Csqrt%7B(x_2%20-%20x_1)%5E2%20+%20(y_2%20-%20y_1)%5E2%7D%0A"></p>
<div id="7fdb47e8" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1">dists <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> X).square().<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).sqrt()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> dists</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="17">
<pre><code>tensor([ 0.000,  5.540,  1.481,  ..., 36.864, 29.651, 37.404])</code></pre>
</div>
</div>
</section>
<section id="calculate-weights" class="level3 page-columns page-full">
<h3 class="anchored" data-anchor-id="calculate-weights">Calculate Weights</h3>
<blockquote class="blockquote">
<p>Calculate weights for each point in the dataset by passing the calculated distances through the normal distribution.</p>
</blockquote>
<p>The <a href="https://www.mathsisfun.com/data/standard-normal-distribution.html">normal distribution</a> is also known as the Gaussian distribution. A distribution is simply a way to describe how data is spread out —&nbsp;this isn’t applicable in our case. What is applicable is the shape of this distribution which we will use to calculate the weights.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Af(x)%20=%20%5Cfrac%7B1%7D%7B%5Csigma%20%5Csqrt%7B2%5Cpi%7D%20%7D%20e%5E%7B-%5Cfrac%7B1%7D%7B2%7D%5Cleft(%5Cfrac%7Bx-%5Cmu%7D%7B%5Csigma%7D%5Cright)%5E2%7D%0A"></p>
<div id="2ab59a9d" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> gauss_kernel(x, mean, std):</span>
<span id="cb9-2">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> torch.exp(<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>(x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> mean) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> std <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (std <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> torch.sqrt(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> tensor(torch.pi)))</span></code></pre></div></div>
</div>
<p>This is how it looks like.</p>
<div id="6e10abbe" class="cell page-columns page-full">
<div class="cell-output cell-output-display column-page">
<div>                            <div id="fbdc4f5c-47f9-4245-9dfc-d6eb46f1ae14" class="plotly-graph-div" style="height:576px; width:1024px;"></div>            <script type="text/javascript">                require(["plotly"], function(Plotly) {                    window.PLOTLYENV=window.PLOTLYENV || {};                                    if (document.getElementById("fbdc4f5c-47f9-4245-9dfc-d6eb46f1ae14")) {                    Plotly.newPlot(                        "fbdc4f5c-47f9-4245-9dfc-d6eb46f1ae14",                        [{"marker":{"color":"#d92310"},"x":[0.0,0.10101009905338287,0.20202019810676575,0.3030303120613098,0.4040403962135315,0.5050504803657532,0.6060606241226196,0.7070707082748413,0.808080792427063,0.9090908765792847,1.0101009607315063,1.111111044883728,1.2121212482452393,1.313131332397461,1.4141414165496826,1.5151515007019043,1.616161584854126,1.7171716690063477,1.8181817531585693,1.919191837310791,2.0202019214630127,2.1212120056152344,2.222222089767456,2.3232321739196777,2.4242424964904785,2.5252525806427,2.626262664794922,2.7272727489471436,2.8282828330993652,2.929292917251587,3.0303030014038086,3.1313130855560303,3.232323169708252,3.3333332538604736,3.4343433380126953,3.535353422164917,3.6363635063171387,3.7373735904693604,3.838383674621582,3.9393937587738037,4.040403842926025,4.141414165496826,4.242424011230469,4.3434343338012695,4.444444179534912,4.545454502105713,4.6464643478393555,4.747474670410156,4.848484992980957,4.9494948387146,5.0505051612854,5.151515007019043,5.252525329589844,5.3535356521606445,5.454545497894287,5.555555820465088,5.6565656661987305,5.757575988769531,5.858585834503174,5.959596157073975,6.060606002807617,6.161616325378418,6.2626261711120605,6.363636493682861,6.464646339416504,6.565656661987305,6.666666507720947,6.767676830291748,6.868687152862549,6.969696998596191,7.070707321166992,7.171717166900635,7.2727274894714355,7.373737335205078,7.474747657775879,7.5757575035095215,7.676767826080322,7.777777671813965,7.878787994384766,7.979797840118408,8.08080768585205,8.181818008422852,8.282828330993652,8.383838653564453,8.484848976135254,8.585858345031738,8.686868667602539,8.78787899017334,8.88888931274414,8.989898681640625,9.090909004211426,9.191919326782227,9.292929649353027,9.393939018249512,9.494949340820312,9.595959663391113,9.696969985961914,9.797979354858398,9.8989896774292,10.0],"y":[0.1595769077539444,0.15944671630859375,0.15905675292015076,0.15840892493724823,0.15750640630722046,0.15635357797145844,0.15495601296424866,0.15332044661045074,0.15145468711853027,0.1493675857782364,0.14706897735595703,0.144569531083107,0.14188076555728912,0.13901486992835999,0.13598470389842987,0.13280360400676727,0.1294853538274765,0.12604409456253052,0.12249413877725601,0.11885000765323639,0.11512617766857147,0.11133713275194168,0.10749714821577072,0.10362031310796738,0.09972036629915237,0.0958106592297554,0.09190409630537033,0.08801301568746567,0.08414918929338455,0.08032375574111938,0.07654716819524765,0.07282915711402893,0.06917870044708252,0.06560403108596802,0.06211260333657265,0.058711059391498566,0.055405277758836746,0.05220034345984459,0.04910058155655861,0.046109553426504135,0.043230101466178894,0.040464334189891815,0.037813760340213776,0.035279154777526855,0.03286076337099075,0.030558215454220772,0.028370661661028862,0.026296738535165787,0.024334654211997986,0.02248224802315235,0.020736966282129288,0.019095974043011665,0.017556147649884224,0.016114164143800735,0.014766494743525982,0.013509458862245083,0.01233927346765995,0.011252064257860184,0.01024391409009695,0.009310876950621605,0.008449019864201546,0.0076544322073459625,0.006923263426870108,0.006251719314604998,0.005636107642203569,0.005072826519608498,0.004558395594358444,0.0040894486010074615,0.0036627596709877253,0.0032752424012869596,0.0029239447321742773,0.0026060710661113262,0.002318964572623372,0.002060123486444354,0.0018271876033395529,0.0016179465455934405,0.0014303296338766813,0.0012624067021533847,0.0011123797157779336,0.0009785847505554557,0.000859478022903204,0.0007536362973041832,0.000659750250633806,0.0005766188842244446,0.0005031400360167027,0.00043830907088704407,0.00038120849058032036,0.0003310059546492994,0.0002869457530323416,0.0002483450516592711,0.0002145861799363047,0.00018511386588215828,0.00015942890604492277,0.00013708397455047816,0.00011767854448407888,0.00010085522080771625,8.629600051790476e-05,7.371818355750293e-05,6.287076394073665e-05,5.353209053282626e-05],"type":"scatter"}],                        {"template":{"data":{"scatter":[{"marker":{"color":"#d92310"},"type":"scatter"}]},"layout":{"height":576,"paper_bgcolor":"#fcfcfc","plot_bgcolor":"#fcfcfc","width":1024}}},                        {"responsive": true}                    ).then(function(){
                            
var gd = document.getElementById('fbdc4f5c-47f9-4245-9dfc-d6eb46f1ae14');
var x = new MutationObserver(function (mutations, observer) {{
        var display = window.getComputedStyle(gd).display;
        if (!display || display === 'none') {{
            console.log([gd, 'removed!']);
            Plotly.purge(gd);
            observer.disconnect();
        }}
}});

// Listen for the removal of the full notebook cells
var notebookContainer = gd.closest('#notebook-container');
if (notebookContainer) {{
    x.observe(notebookContainer, {childList: true});
}}

// Listen for the clearing of the current output cell
var outputEl = gd.closest('.output');
if (outputEl) {{
    x.observe(outputEl, {childList: true});
}}

                        })                };                });            </script>        </div>
</div>
</div>
<p>From the shape of this graph, we can see that larger values of <img src="https://latex.codecogs.com/png.latex?x"> give smaller values of <img src="https://latex.codecogs.com/png.latex?y">, which is what we want —&nbsp;longer distances should have smaller weights meaning they have a smaller effect on the new position of the point.</p>
<p>We can control the rate at which the weights go to zero by varying what’s known as the bandwidth, or the standard deviation. The graph above is generated with a bandwith of 2.5.</p>
<p>The graph below is generated with a bandwidth of 1.</p>
<div id="2a0d7077" class="cell page-columns page-full">
<div class="cell-output cell-output-display column-page">
<div>                            <div id="7f9397ad-85b8-410f-9dbb-2557538070df" class="plotly-graph-div" style="height:576px; width:1024px;"></div>            <script type="text/javascript">                require(["plotly"], function(Plotly) {                    window.PLOTLYENV=window.PLOTLYENV || {};                                    if (document.getElementById("7f9397ad-85b8-410f-9dbb-2557538070df")) {                    Plotly.newPlot(                        "7f9397ad-85b8-410f-9dbb-2557538070df",                        [{"marker":{"color":"#d92310"},"x":[0.0,0.10101009905338287,0.20202019810676575,0.3030303120613098,0.4040403962135315,0.5050504803657532,0.6060606241226196,0.7070707082748413,0.808080792427063,0.9090908765792847,1.0101009607315063,1.111111044883728,1.2121212482452393,1.313131332397461,1.4141414165496826,1.5151515007019043,1.616161584854126,1.7171716690063477,1.8181817531585693,1.919191837310791,2.0202019214630127,2.1212120056152344,2.222222089767456,2.3232321739196777,2.4242424964904785,2.5252525806427,2.626262664794922,2.7272727489471436,2.8282828330993652,2.929292917251587,3.0303030014038086,3.1313130855560303,3.232323169708252,3.3333332538604736,3.4343433380126953,3.535353422164917,3.6363635063171387,3.7373735904693604,3.838383674621582,3.9393937587738037,4.040403842926025,4.141414165496826,4.242424011230469,4.3434343338012695,4.444444179534912,4.545454502105713,4.6464643478393555,4.747474670410156,4.848484992980957,4.9494948387146,5.0505051612854,5.151515007019043,5.252525329589844,5.3535356521606445,5.454545497894287,5.555555820465088,5.6565656661987305,5.757575988769531,5.858585834503174,5.959596157073975,6.060606002807617,6.161616325378418,6.2626261711120605,6.363636493682861,6.464646339416504,6.565656661987305,6.666666507720947,6.767676830291748,6.868687152862549,6.969696998596191,7.070707321166992,7.171717166900635,7.2727274894714355,7.373737335205078,7.474747657775879,7.5757575035095215,7.676767826080322,7.777777671813965,7.878787994384766,7.979797840118408,8.08080768585205,8.181818008422852,8.282828330993652,8.383838653564453,8.484848976135254,8.585858345031738,8.686868667602539,8.78787899017334,8.88888931274414,8.989898681640625,9.090909004211426,9.191919326782227,9.292929649353027,9.393939018249512,9.494949340820312,9.595959663391113,9.696969985961914,9.797979354858398,9.8989896774292,10.0],"y":[0.3989422917366028,0.39691224694252014,0.3908839225769043,0.38103950023651123,0.3676724135875702,0.35117292404174805,0.332008957862854,0.31070446968078613,0.2878154516220093,0.2639061510562897,0.2395266741514206,0.21519248187541962,0.19136790931224823,0.16845351457595825,0.14677762985229492,0.12659268081188202,0.10807523876428604,0.09132982790470123,0.07639553397893906,0.06325461715459824,0.051842425018548965,0.04205787181854248,0.03377366065979004,0.026845896616578102,0.02112254500389099,0.0164506733417511,0.012682069092988968,0.009677547961473465,0.0073098656721413136,0.005465405061841011,0.004044866189360619,0.0029631592333316803,0.0021486938931047916,0.001542279263958335,0.001095772604458034,0.0007706313044764102,0.0005364654352888465,0.0003696628555189818,0.0002521381829865277,0.00017023166583385319,0.00011376560723874718,7.525753608206287e-05,4.9278671212960035e-05,3.1940071494318545e-05,2.0491905161179602e-05,1.3013589523325209e-05,8.180530130630359e-06,5.090186732559232e-06,3.13512373395497e-06,1.9113738289888715e-06,1.1534652912814636e-06,6.890224426570057e-07,4.0740854956311523e-07,2.384490471740719e-07,1.3814370447562396e-07,7.921985911707452e-08,4.4968398782430086e-08,2.5266686520808435e-08,1.4052678132259189e-08,7.736388418777551e-09,4.215864102263822e-09,2.274066712715239e-09,1.2141988525726788e-09,6.417175124617813e-10,3.357128741665605e-10,1.7384393924402275e-10,8.910907428605341e-11,4.5211799581945655e-11,2.2706491201174295e-11,1.1288052090274725e-11,5.554624035036815e-12,2.705584888074153e-12,1.3044731310765667e-12,6.225581573697514e-13,2.940975371221177e-13,1.3752246683009645e-13,6.365353665167828e-14,2.91637340091213e-14,1.3226028989187216e-14,5.93727998487786e-15,2.6382372154287346e-15,1.160399879991962e-15,5.052075603734663e-16,2.17721838453168e-16,9.287577300300494e-17,3.9217019961665717e-17,1.6391296867426264e-17,6.781416499660302e-18,2.7771273849293945e-18,1.1257566245328715e-18,4.517084949629707e-19,1.794073710776881e-19,7.053272148011633e-20,2.744822440642201e-20,1.0573155067797779e-20,4.031452931178279e-21,1.5215580441903595e-21,5.684454437762772e-22,2.1020951984089623e-22,7.694598494446235e-23],"type":"scatter"}],                        {"template":{"data":{"scatter":[{"marker":{"color":"#d92310"},"type":"scatter"}]},"layout":{"height":576,"paper_bgcolor":"#fcfcfc","plot_bgcolor":"#fcfcfc","width":1024}}},                        {"responsive": true}                    ).then(function(){
                            
var gd = document.getElementById('7f9397ad-85b8-410f-9dbb-2557538070df');
var x = new MutationObserver(function (mutations, observer) {{
        var display = window.getComputedStyle(gd).display;
        if (!display || display === 'none') {{
            console.log([gd, 'removed!']);
            Plotly.purge(gd);
            observer.disconnect();
        }}
}});

// Listen for the removal of the full notebook cells
var notebookContainer = gd.closest('#notebook-container');
if (notebookContainer) {{
    x.observe(notebookContainer, {childList: true});
}}

// Listen for the clearing of the current output cell
var outputEl = gd.closest('.output');
if (outputEl) {{
    x.observe(outputEl, {childList: true});
}}

                        })                };                });            </script>        </div>
</div>
</div>
<p>Let’s get our weights now.</p>
<div id="7d500f0a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1">gauss_kernel(dists, mean<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, std<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.5</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="23">
<pre><code>tensor([    0.160,     0.014,     0.134,  ...,     0.000,     0.000,     0.000])</code></pre>
</div>
</div>
<div id="85a2e88a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb12" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1">bw <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.5</span></span>
<span id="cb12-2">ws <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> gauss_kernel(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>dists, mean<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, std<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>bw)</span></code></pre></div></div>
</div>
</section>
<section id="move-the-point" class="level3 page-columns page-full">
<h3 class="anchored" data-anchor-id="move-the-point">Move the Point</h3>
<blockquote class="blockquote">
<p>Calculate the weighted average for all points in the dataset. This weighted average is the new location for <img src="https://latex.codecogs.com/png.latex?x"></p>
</blockquote>
<div id="5c35e724" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb13" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1">ws.shape, X.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="25">
<pre><code>(torch.Size([1500]), torch.Size([1500, 2]))</code></pre>
</div>
</div>
<div id="9a4a011e" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb15" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb15-1">ws[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>].shape, X.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="26">
<pre><code>(torch.Size([1500, 1]), torch.Size([1500, 2]))</code></pre>
</div>
</div>
<p>Below is the formula for <a href="https://www.mathsisfun.com/data/weighted-mean.html">weighted average</a>.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7B%5Csum%20wx%7D%7B%5Csum%20w%7D%0A"></p>
<p>In words, multiply each data point in the set with its corresponding weight and sum all products. Divide that with the sum of all weights.</p>
<div id="fb2d1993" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb17" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb17-1">ws[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> X, ws[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> X[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, :]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="27">
<pre><code>(tensor([[     0.097,     -3.223],
         [     0.061,     -0.331],
         [     0.277,     -2.738],
         ...,
         [     0.000,      0.000],
         [     0.000,      0.000],
         [     0.000,      0.000]]),
 tensor([ 0.097, -3.223]))</code></pre>
</div>
</div>
<p>Let’s calculate the weighted average and assign it as the new location for our point <img src="https://latex.codecogs.com/png.latex?x">.</p>
<div id="10699daf" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb19" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb19-1">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (ws[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> X).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> ws.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> x</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="28">
<pre><code>tensor([  1.695, -20.786])</code></pre>
</div>
</div>
<p>And there you have it! We just moved a single data point.</p>
<p>Let’s do this for all data points and for a single iteration.</p>
<div id="988eda4d" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb21" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb21-1"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, x <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(X):</span>
<span id="cb21-2">    dist <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> X).square().<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).sqrt()</span>
<span id="cb21-3">    ws <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> gauss_kernel(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>dist, mean<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, std<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>bw)</span>
<span id="cb21-4">    X[i] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (ws[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> X).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> ws.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>()</span></code></pre></div></div>
</div>
<div id="c7f563f9" class="cell page-columns page-full">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb22" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb22-1">plot_data(centroids<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, X, n_samples)</span></code></pre></div></div>
<div class="cell-output cell-output-display column-page">
<div>                            <div id="a11bb9b5-89e3-4ba7-9e87-382a817512e4" class="plotly-graph-div" style="height:576px; width:1024px;"></div>            <script type="text/javascript">                require(["plotly"], function(Plotly) {                    window.PLOTLYENV=window.PLOTLYENV || {};                                    if (document.getElementById("a11bb9b5-89e3-4ba7-9e87-382a817512e4")) {                    Plotly.newPlot(                        "a11bb9b5-89e3-4ba7-9e87-382a817512e4",                        [{"marker":{"color":"#636EFA","size":3},"mode":"markers","name":"cluster 0","x":[1.6946265697479248,3.449998617172241,2.3729336261749268,1.9416052103042603,3.4232354164123535,1.393724799156189,3.203889846801758,2.742619037628174,0.9621626734733582,4.264341831207275,2.7116641998291016,3.4931559562683105,2.3637421131134033,0.7502619624137878,0.5140782594680786,1.3128371238708496,2.467108964920044,2.726853609085083,3.3970415592193604,1.8129693269729614,1.168636679649353,3.9801809787750244,2.325812578201294,2.972182512283325,2.4004223346710205,2.5505640506744385,-0.5080786943435669,2.2283055782318115,3.9053497314453125,2.2120308876037598,3.4893414974212646,2.197722911834717,2.6455559730529785,2.0543947219848633,1.4671787023544312,2.0673391819000244,1.7018321752548218,2.925679922103882,1.859802484512329,1.6141977310180664,0.49830183386802673,2.999140739440918,2.480736494064331,4.006897449493408,2.224219799041748,3.160285711288452,1.8546350002288818,2.966703176498413,2.0785467624664307,3.4128572940826416,2.648806095123291,2.206836700439453,2.9089088439941406,1.4336549043655396,2.9363622665405273,2.9449901580810547,1.644398808479309,3.014716148376465,2.11179780960083,3.026470422744751,1.8596433401107788,1.5716087818145752,2.214670419692993,2.7771472930908203,2.9622044563293457,2.977346181869507,2.4111127853393555,0.7618668675422668,3.719949960708618,2.295081615447998,2.6981592178344727,1.8176337480545044,2.736699342727661,3.408546209335327,4.097562789916992,3.1021454334259033,2.605257034301758,2.258788585662842,3.0681488513946533,2.176664113998413,3.029879570007324,2.4986486434936523,3.4964356422424316,2.667665481567383,2.0924112796783447,2.0721352100372314,2.0405476093292236,3.1822311878204346,2.259921073913574,3.0854318141937256,3.005093812942505,2.7969536781311035,2.761613607406616,3.544318437576294,0.8529166579246521,1.885594367980957,2.3264403343200684,1.7199219465255737,3.3416733741760254,1.5913722515106201,0.5495020747184753,3.0220677852630615,3.016310691833496,2.586745262145996,2.9057140350341797,2.019304037094116,2.019484281539917,2.7870585918426514,1.8434600830078125,2.2048447132110596,2.3979060649871826,3.420743465423584,2.8256638050079346,3.288011312484741,2.5389583110809326,2.7542002201080322,1.7702414989471436,2.512371063232422,2.307831287384033,2.410545587539673,2.1187453269958496,2.324117660522461,2.1551711559295654,2.945241689682007,2.864262580871582,2.3277230262756348,2.9510087966918945,2.5914838314056396,2.5753321647644043,2.2084193229675293,3.576427459716797,2.9279403686523438,1.7457350492477417,2.409273624420166,2.63500714302063,2.9217264652252197,2.5131676197052,2.643481731414795,2.831210136413574,3.8069164752960205,2.0308752059936523,2.713686227798462,2.738316774368286,2.9315781593322754,2.330852508544922,2.486298084259033,2.7511332035064697,2.2206685543060303,3.4792003631591797,3.0461947917938232,2.455667734146118,3.1273677349090576,2.8069722652435303,2.697984457015991,2.962015390396118,3.024524450302124,2.7957241535186768,2.140803575515747,2.7702906131744385,1.7410404682159424,1.7314332723617554,2.5178892612457275,2.8300509452819824,2.193343162536621,2.6096065044403076,1.878253698348999,2.636425018310547,2.766038656234741,2.6407313346862793,2.6477770805358887,3.275813341140747,2.4590258598327637,2.6642305850982666,2.0397214889526367,3.8388824462890625,3.5617833137512207,2.892345905303955,2.5714948177337646,2.391604423522949,2.9260976314544678,2.4415640830993652,2.607224941253662,2.0695953369140625,2.563575506210327,2.6549837589263916,3.3067409992218018,2.0315568447113037,1.911465048789978,2.7747244834899902,2.5050957202911377,3.198904037475586,2.2129693031311035,2.6859564781188965,2.9133646488189697,2.0121095180511475,2.1648502349853516,3.098203182220459,2.3815953731536865,2.8553466796875,2.583845376968384,2.1685073375701904,2.1501879692077637,3.8614518642425537,2.5223875045776367,2.5367186069488525,2.2027230262756348,2.9115684032440186,2.7739622592926025,2.5361804962158203,3.066636085510254,2.689459800720215,2.881826162338257,2.475058078765869,2.498260021209717,2.6855835914611816,2.77927827835083,2.5728089809417725,3.263051986694336,1.9935120344161987,2.4182701110839844,2.110403060913086,2.862842559814453,2.3278934955596924,2.545283317565918,2.464959144592285,2.721184492111206,2.8335001468658447,3.1609034538269043,2.702655553817749,2.685124397277832,2.9480550289154053,2.4472742080688477,2.613926887512207,2.427957773208618,2.910409927368164,2.6316471099853516,2.5788679122924805,2.631870746612549,2.508378028869629,2.804633617401123,2.0834224224090576,2.1646745204925537,2.6558806896209717,2.742758274078369,2.6148931980133057,2.848088502883911,2.5519447326660156,2.401672601699829,2.2792060375213623,2.2420196533203125],"y":[-20.78610610961914,-22.398971557617188,-20.914709091186523,-21.91057777404785,-21.66291618347168,-21.51350212097168,-20.268638610839844,-20.216014862060547,-21.380203247070312,-21.513076782226562,-20.512157440185547,-21.819744110107422,-21.34463119506836,-21.38899803161621,-20.501529693603516,-22.269506454467773,-21.191009521484375,-19.07061195373535,-21.74657440185547,-21.613126754760742,-20.02367401123047,-22.10400390625,-21.350706100463867,-20.969181060791016,-21.361974716186523,-21.465110778808594,-22.06197738647461,-20.40784454345703,-21.180397033691406,-22.87186622619629,-21.50389862060547,-20.57219886779785,-21.041126251220703,-20.54086685180664,-22.4803524017334,-21.612083435058594,-20.219520568847656,-21.303709030151367,-21.42768669128418,-20.700531005859375,-20.79828643798828,-20.95842170715332,-21.872081756591797,-20.31779670715332,-21.287094116210938,-20.416881561279297,-21.03209686279297,-20.076547622680664,-20.57390785217285,-22.04358673095703,-21.205764770507812,-20.807540893554688,-19.673297882080078,-19.82783317565918,-21.308837890625,-22.010562896728516,-21.35736846923828,-21.13275718688965,-21.48708724975586,-20.770605087280273,-20.378089904785156,-20.819568634033203,-20.785449981689453,-20.39082145690918,-21.122148513793945,-21.70020294189453,-21.696765899658203,-21.658658981323242,-22.364282608032227,-20.849689483642578,-22.194488525390625,-20.36215591430664,-21.294260025024414,-21.9702091217041,-21.572914123535156,-21.15321922302246,-21.525487899780273,-21.158227920532227,-21.883634567260742,-21.11046600341797,-21.829654693603516,-21.11017417907715,-21.445404052734375,-21.607295989990234,-21.58856773376465,-21.04619598388672,-21.244075775146484,-21.086017608642578,-21.663700103759766,-21.057340621948242,-21.590354919433594,-20.262195587158203,-20.756179809570312,-21.670854568481445,-21.991043090820312,-21.17201805114746,-21.090423583984375,-20.667747497558594,-21.684301376342773,-21.3138427734375,-21.11836814880371,-20.80900764465332,-20.868244171142578,-21.252674102783203,-21.69295310974121,-21.637887954711914,-23.49968910217285,-21.765769958496094,-22.238492965698242,-20.580352783203125,-21.533187866210938,-21.184926986694336,-20.863258361816406,-21.339921951293945,-21.475404739379883,-21.440658569335938,-21.252796173095703,-21.59950828552246,-21.027490615844727,-20.52918815612793,-20.781038284301758,-21.412921905517578,-20.053823471069336,-21.155458450317383,-21.3143253326416,-21.153533935546875,-21.5880069732666,-21.325592041015625,-21.92909049987793,-20.99647331237793,-18.872333526611328,-21.253009796142578,-21.64813232421875,-20.853683471679688,-21.55528450012207,-21.112478256225586,-20.518156051635742,-21.478647232055664,-21.50851058959961,-19.923219680786133,-21.565340042114258,-21.167688369750977,-21.16850471496582,-21.068004608154297,-20.872211456298828,-21.036710739135742,-21.625194549560547,-20.59202003479004,-21.168167114257812,-21.545501708984375,-21.31072425842285,-21.959199905395508,-21.424419403076172,-21.009016036987305,-20.991405487060547,-21.09759521484375,-21.347339630126953,-21.20339012145996,-21.249305725097656,-21.098363876342773,-21.064701080322266,-21.17884063720703,-20.921052932739258,-21.445514678955078,-20.860958099365234,-21.29085350036621,-21.13347625732422,-21.505151748657227,-21.54643440246582,-21.17691421508789,-20.373516082763672,-21.412731170654297,-21.30141258239746,-21.327178955078125,-21.86045265197754,-20.812671661376953,-21.842405319213867,-21.362932205200195,-21.701045989990234,-20.939922332763672,-21.220561981201172,-21.1634521484375,-20.771873474121094,-21.785940170288086,-20.998600006103516,-20.712705612182617,-21.211671829223633,-21.136688232421875,-21.19127655029297,-21.47712516784668,-20.701736450195312,-21.429153442382812,-21.155410766601562,-21.768978118896484,-21.2914981842041,-21.080453872680664,-20.50115203857422,-21.09111785888672,-20.604705810546875,-21.249418258666992,-21.103071212768555,-21.10801887512207,-17.54497718811035,-20.840980529785156,-21.6018123626709,-21.115680694580078,-21.677776336669922,-21.025733947753906,-21.15434455871582,-20.728164672851562,-20.935171127319336,-20.97151756286621,-21.09917449951172,-21.227930068969727,-21.217927932739258,-20.840961456298828,-21.27079963684082,-21.020103454589844,-20.885765075683594,-20.994483947753906,-20.83262825012207,-20.91411781311035,-21.206768035888672,-21.077322006225586,-21.501840591430664,-20.984357833862305,-20.880023956298828,-21.741382598876953,-21.312536239624023,-21.19350242614746,-21.225488662719727,-21.466764450073242,-21.28557586669922,-21.199525833129883,-21.347515106201172,-21.2202091217041,-21.30464744567871,-21.373323440551758,-21.351539611816406,-21.092405319213867,-20.906835556030273,-21.136032104492188,-21.11936378479004,-21.0457820892334,-21.113126754760742,-21.124452590942383,-21.150630950927734,-21.125343322753906,-20.96417999267578,-21.453123092651367],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"#EF553B","size":3},"mode":"markers","name":"cluster 1","x":[10.553921699523926,10.378192901611328,11.677305221557617,9.76516056060791,11.228522300720215,10.852045059204102,10.936358451843262,10.848250389099121,11.160809516906738,11.177790641784668,11.086302757263184,12.732450485229492,12.019720077514648,12.866479873657227,9.845115661621094,10.165964126586914,11.27199935913086,12.764793395996094,10.379088401794434,11.732418060302734,12.765474319458008,12.87234878540039,11.03215217590332,11.526556968688965,11.153594017028809,11.360498428344727,10.894035339355469,11.902581214904785,12.668740272521973,11.266735076904297,10.382909774780273,12.255353927612305,11.316174507141113,10.6468505859375,11.758978843688965,10.968881607055664,10.567042350769043,11.527205467224121,11.820052146911621,11.288623809814453,8.06213092803955,11.279064178466797,11.128617286682129,10.943465232849121,11.892148971557617,10.355629920959473,11.576713562011719,10.511497497558594,15.913922309875488,10.637694358825684,9.707133293151855,11.10561466217041,12.0292329788208,10.644925117492676,11.2578763961792,11.146879196166992,10.769599914550781,11.154306411743164,11.724708557128906,11.759297370910645,12.35037612915039,11.284743309020996,10.5274076461792,11.63113784790039,9.534015655517578,10.978789329528809,10.788853645324707,11.196309089660645,11.002007484436035,12.166753768920898,11.288334846496582,11.02209186553955,10.786494255065918,10.937630653381348,11.072771072387695,11.059539794921875,12.039098739624023,10.596759796142578,15.357443809509277,11.083370208740234,10.876011848449707,10.060815811157227,12.093324661254883,10.996378898620605,11.774632453918457,10.139411926269531,12.340705871582031,10.260533332824707,9.196358680725098,11.163867950439453,11.441466331481934,12.043437004089355,9.849756240844727,12.309586524963379,12.509374618530273,10.862445831298828,11.183209419250488,10.974650382995605,11.28494930267334,12.382393836975098,10.832682609558105,12.110004425048828,11.483365058898926,10.37495231628418,10.324080467224121,10.592535972595215,11.095077514648438,11.124641418457031,12.197379112243652,9.373515129089355,11.11252498626709,11.94969367980957,11.12753963470459,10.132634162902832,11.342312812805176,11.11259937286377,10.59852409362793,10.211478233337402,11.423558235168457,10.872918128967285,9.833968162536621,11.137648582458496,10.324847221374512,11.047890663146973,10.782092094421387,11.428747177124023,9.23951244354248,11.218369483947754,11.050278663635254,11.52939510345459,10.494760513305664,10.894204139709473,11.551217079162598,11.20985221862793,11.042498588562012,11.350503921508789,11.514573097229004,11.341403007507324,10.360342979431152,12.553485870361328,10.900530815124512,11.507806777954102,10.562841415405273,11.215763092041016,11.002530097961426,10.667011260986328,10.78979778289795,10.242466926574707,11.060234069824219,10.982453346252441,11.299104690551758,11.412644386291504,12.082005500793457,11.071557998657227,11.304062843322754,11.033889770507812,11.017111778259277,11.665783882141113,10.76292610168457,9.687395095825195,11.04201602935791,10.665197372436523,11.474325180053711,12.198394775390625,11.315717697143555,10.77605152130127,11.443704605102539,10.869242668151855,10.697967529296875,10.52572250366211,11.447805404663086,11.062193870544434,11.396424293518066,10.962074279785156,10.874069213867188,11.248862266540527,10.715302467346191,11.199419021606445,10.606327056884766,11.109124183654785,10.4501371383667,11.697257041931152,11.148107528686523,11.332337379455566,10.827033996582031,11.299649238586426,10.855655670166016,10.885908126831055,11.229434967041016,11.059819221496582,10.637429237365723,11.22687816619873,10.234177589416504,10.756370544433594,11.156249046325684,11.006500244140625,10.10341739654541,11.128985404968262,11.35232925415039,11.300151824951172,11.051115989685059,11.308767318725586,11.197009086608887,11.690791130065918,11.16855239868164,10.595367431640625,11.073407173156738,6.6604461669921875,11.196741104125977,11.813139915466309,10.482831954956055,11.021352767944336,11.102421760559082,10.738703727722168,11.164712905883789,10.927050590515137,11.755099296569824,11.31787395477295,11.440556526184082,11.274033546447754,11.006196022033691,10.944647789001465,9.432446479797363,10.864757537841797,11.010411262512207,9.830744743347168,10.841902732849121,10.458699226379395,11.239252090454102,11.328508377075195,9.075081825256348,11.437505722045898,10.664111137390137,10.81592845916748,11.136358261108398,11.018789291381836,11.04726791381836,12.124147415161133,11.160086631774902,9.763992309570312,10.939802169799805,11.361539840698242,11.062042236328125,11.21703815460205,11.084966659545898,11.000564575195312,11.125944137573242,7.740894794464111,11.009302139282227,11.03368854522705],"y":[10.839703559875488,10.186578750610352,12.088871002197266,11.572620391845703,10.504829406738281,11.270042419433594,9.26921272277832,10.038911819458008,11.434706687927246,12.629814147949219,10.871581077575684,12.028068542480469,11.07958698272705,10.428178787231445,11.344042778015137,10.428462028503418,10.490863800048828,11.344935417175293,12.197561264038086,9.566756248474121,9.817669868469238,11.714271545410156,9.960370063781738,12.360904693603516,11.22794246673584,10.894606590270996,10.533679008483887,10.630075454711914,9.87071418762207,9.821185111999512,9.701789855957031,10.042207717895508,9.809471130371094,11.43781566619873,10.407062530517578,10.574695587158203,11.926901817321777,12.11008071899414,11.049091339111328,10.14609432220459,10.430465698242188,11.775084495544434,11.677364349365234,9.301335334777832,10.770838737487793,12.002434730529785,10.31279182434082,11.391910552978516,11.587087631225586,11.656115531921387,11.476985931396484,11.198649406433105,8.82095718383789,11.313366889953613,10.857261657714844,11.509666442871094,11.331183433532715,10.272746086120605,10.65829086303711,8.501448631286621,10.625774383544922,12.26149845123291,9.499472618103027,11.583186149597168,11.289894104003906,11.326577186584473,11.532890319824219,11.105368614196777,11.01874828338623,9.384239196777344,11.984138488769531,10.91139030456543,11.137113571166992,10.589387893676758,10.182755470275879,9.874202728271484,11.294371604919434,10.01098918914795,9.999019622802734,10.675689697265625,10.543596267700195,9.270455360412598,12.035409927368164,11.598392486572266,11.212035179138184,10.543935775756836,12.32702350616455,10.308807373046875,9.472911834716797,11.610387802124023,10.236538887023926,10.37879753112793,11.275368690490723,11.778006553649902,10.561485290527344,11.955370903015137,10.657002449035645,12.045339584350586,11.43898868560791,10.645210266113281,10.878558158874512,10.696368217468262,10.704458236694336,10.679771423339844,10.531181335449219,10.0133695602417,11.43203353881836,9.703680038452148,9.909550666809082,10.693717002868652,10.827871322631836,10.224893569946289,11.45480728149414,11.866963386535645,11.744616508483887,12.504663467407227,10.240961074829102,10.940946578979492,11.098469734191895,10.779125213623047,10.96560287475586,11.282730102539062,10.919716835021973,10.956759452819824,11.393665313720703,10.90475845336914,11.064666748046875,9.908555030822754,11.773627281188965,11.363913536071777,11.369292259216309,10.380696296691895,8.743345260620117,9.939522743225098,11.944669723510742,11.036115646362305,10.62712574005127,11.185225486755371,11.206557273864746,10.050843238830566,10.524185180664062,10.2691011428833,10.258854866027832,10.961446762084961,10.621742248535156,11.220978736877441,11.31548023223877,10.203405380249023,10.4852876663208,10.907896041870117,9.832657814025879,10.488471031188965,10.739477157592773,11.731141090393066,11.168075561523438,10.574892044067383,11.775773048400879,10.11162281036377,11.293416023254395,10.826921463012695,10.837160110473633,10.772971153259277,10.462738037109375,11.83816909790039,10.473282814025879,10.910591125488281,10.396522521972656,11.27634334564209,11.158547401428223,9.919575691223145,10.66947078704834,10.751543045043945,10.147286415100098,10.69190788269043,10.694835662841797,11.091699600219727,11.220097541809082,11.514409065246582,10.856880187988281,10.800125122070312,10.943448066711426,10.741830825805664,10.679606437683105,10.934500694274902,11.489663124084473,11.093504905700684,10.951253890991211,10.59508228302002,10.92122745513916,11.007454872131348,10.430818557739258,11.175667762756348,11.588040351867676,10.883882522583008,10.637737274169922,11.37508773803711,10.310274124145508,10.590265274047852,11.624344825744629,10.90420913696289,11.307595252990723,10.851158142089844,10.442911148071289,10.600739479064941,11.035205841064453,10.590719223022461,10.446906089782715,17.1706485748291,11.1589994430542,10.986806869506836,10.864731788635254,10.806295394897461,10.725379943847656,10.876736640930176,10.656420707702637,11.099913597106934,10.704933166503906,10.5697660446167,10.105047225952148,10.75500202178955,10.636931419372559,11.202589988708496,10.860106468200684,10.799151420593262,10.713971138000488,11.105849266052246,10.867669105529785,11.320473670959473,11.143575668334961,10.949877738952637,9.32813835144043,10.729281425476074,11.243111610412598,10.924150466918945,10.770785331726074,10.970190048217773,9.487630844116211,10.352680206298828,10.792567253112793,10.992082595825195,10.991250038146973,10.314839363098145,10.948410987854004,10.87873363494873,10.77352237701416,10.73262882232666,10.933393478393555,10.832498550415039,10.834753036499023,10.474137306213379],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"#00CC96","size":3},"mode":"markers","name":"cluster 2","x":[-21.09304428100586,-18.89359474182129,-19.406923294067383,-17.72010040283203,-17.608123779296875,-19.196523666381836,-18.72412872314453,-16.56171226501465,-18.312789916992188,-19.164260864257812,-18.526185989379883,-17.9394588470459,-18.133909225463867,-19.553863525390625,-17.998647689819336,-18.76464080810547,-18.749082565307617,-17.27752685546875,-17.42732048034668,-17.758974075317383,-18.442039489746094,-18.77231216430664,-19.320655822753906,-19.9549560546875,-18.55945587158203,-18.567773818969727,-18.347375869750977,-16.82990264892578,-20.67626953125,-19.370582580566406,-17.742374420166016,-18.299108505249023,-18.769290924072266,-20.718910217285156,-18.122543334960938,-18.798185348510742,-18.142642974853516,-17.372394561767578,-17.59496307373047,-19.159996032714844,-19.624631881713867,-17.715282440185547,-17.53016471862793,-18.60016441345215,-17.694026947021484,-17.728857040405273,-18.787425994873047,-18.19661521911621,-19.195695877075195,-19.298927307128906,-18.494298934936523,-18.57719612121582,-17.953712463378906,-17.67292022705078,-19.66877555847168,-19.57184410095215,-18.879972457885742,-19.587005615234375,-18.46196174621582,-19.900075912475586,-20.5544490814209,-18.98872947692871,-19.79622459411621,-19.60041618347168,-19.380680084228516,-18.974096298217773,-18.48822593688965,-16.70694351196289,-17.81269645690918,-19.056983947753906,-19.056087493896484,-17.974769592285156,-19.04264259338379,-19.20612335205078,-18.685165405273438,-20.333818435668945,-21.989877700805664,-18.28467559814453,-19.16360092163086,-18.646310806274414,-16.830665588378906,-20.961109161376953,-18.360748291015625,-17.928024291992188,-19.579891204833984,-19.51454734802246,-18.261838912963867,-18.96518325805664,-18.016895294189453,-18.086570739746094,-19.093307495117188,-17.65562629699707,-18.929523468017578,-21.462553024291992,-19.808687210083008,-18.836393356323242,-17.887144088745117,-18.851856231689453,-18.152788162231445,-19.6751766204834,-18.515289306640625,-19.173559188842773,-18.54190444946289,-19.689653396606445,-18.82146453857422,-18.749671936035156,-17.614185333251953,-17.21860694885254,-18.9287166595459,-17.6899471282959,-18.76860237121582,-18.22214126586914,-21.157909393310547,-18.471590042114258,-17.670778274536133,-18.673521041870117,-18.626354217529297,-19.01644515991211,-18.120332717895508,-19.390623092651367,-19.211639404296875,-18.12376594543457,-18.60129737854004,-18.978979110717773,-18.32505989074707,-18.144397735595703,-19.671586990356445,-20.552244186401367,-19.256765365600586,-18.154090881347656,-18.16156005859375,-18.18482208251953,-18.783172607421875,-20.003801345825195,-18.83969497680664,-18.660633087158203,-18.575536727905273,-18.83479881286621,-17.403369903564453,-18.857839584350586,-18.91476821899414,-18.717294692993164,-18.958101272583008,-19.43239974975586,-18.36954689025879,-18.301010131835938,-18.810277938842773,-18.276369094848633,-18.583539962768555,-19.197229385375977,-18.24941635131836,-18.907445907592773,-18.69437026977539,-18.28068733215332,-18.65855598449707,-18.649723052978516,-18.722867965698242,-19.42467498779297,-18.657503128051758,-17.864280700683594,-18.142173767089844,-18.842918395996094,-19.127979278564453,-19.825735092163086,-19.470605850219727,-19.6085147857666,-18.5509033203125,-18.543394088745117,-18.812694549560547,-18.978134155273438,-19.44837760925293,-18.703187942504883,-18.197172164916992,-18.383262634277344,-19.389442443847656,-18.633543014526367,-18.60352897644043,-18.746540069580078,-18.528820037841797,-18.968830108642578,-18.749977111816406,-18.80989646911621,-18.979347229003906,-18.860326766967773,-18.870140075683594,-19.678314208984375,-18.867694854736328,-18.860267639160156,-18.5687255859375,-17.8518009185791,-18.392702102661133,-18.697303771972656,-18.829044342041016,-18.91153907775879,-18.602869033813477,-18.416051864624023,-18.794614791870117,-18.445533752441406,-18.531126022338867,-19.026718139648438,-19.01780891418457,-18.859926223754883,-18.85822105407715,-18.995119094848633,-18.537757873535156,-18.87272071838379,-19.043054580688477,-17.809518814086914,-17.98634147644043,-19.201221466064453,-18.20384407043457,-17.951045989990234,-18.600614547729492,-18.67701530456543,-18.188356399536133,-18.944454193115234,-18.86894416809082,-18.72344398498535,-18.79364585876465,-18.70955467224121,-18.921138763427734,-18.796295166015625,-19.12570571899414,-18.82134246826172,-18.64803695678711,-18.418094635009766,-19.12483024597168,-18.73208236694336,-18.839662551879883,-18.49126434326172,-18.39255142211914,-18.423479080200195,-19.155466079711914,-18.38325309753418,-18.67487335205078,-18.91825294494629,-18.54463768005371,-18.059532165527344,-18.621013641357422,-18.71620750427246,-18.53838539123535,-18.489078521728516,-18.64266014099121,-18.84544563293457,-18.814746856689453,-18.617530822753906,-18.78776741027832,-18.8233585357666,-18.718942642211914,-18.610231399536133],"y":[-3.9462175369262695,-5.365373611450195,-4.698009967803955,-5.4087958335876465,-6.667239665985107,-4.905521869659424,-4.981022357940674,-5.389160633087158,-7.848189353942871,-4.970628261566162,-5.776336669921875,-6.596185207366943,-6.719605922698975,-5.840273857116699,-5.1966872215271,-5.029383659362793,-6.217555046081543,-4.698990345001221,-5.885217189788818,-6.222939968109131,-5.274539470672607,-6.0197858810424805,-5.174999713897705,-5.250279903411865,-5.392036437988281,-5.914658069610596,-6.15630578994751,-6.149774074554443,-4.406765460968018,-5.400729656219482,-5.577253341674805,-5.253227233886719,-5.310800552368164,-4.095142364501953,-6.75627326965332,-5.3935394287109375,-5.1950483322143555,-6.665519714355469,-6.367669582366943,-4.750723361968994,-4.535514831542969,-5.158735275268555,-6.0139312744140625,-7.187129497528076,-5.587166786193848,-2.4393415451049805,-5.48872184753418,-5.893060684204102,-5.169680118560791,-6.436264991760254,-5.768306255340576,-4.737150192260742,-5.613711357116699,-4.408064365386963,-5.445734024047852,-4.248260021209717,-5.840751647949219,-6.01210880279541,-4.921758651733398,-4.475790977478027,-4.6717448234558105,-4.17664098739624,-5.770675182342529,-5.62941312789917,-5.100161552429199,-6.251237392425537,-5.8424153327941895,-4.756065845489502,-5.306107521057129,-5.464851379394531,-4.208014965057373,-5.63125467300415,-5.0065155029296875,-5.144907474517822,-5.557775497436523,-5.516348838806152,-4.987445831298828,-6.136447906494141,-5.273672103881836,-6.760018348693848,-7.779770374298096,-7.555179595947266,-3.627814769744873,-4.708025932312012,-4.636620998382568,-4.975568771362305,-3.8631861209869385,-5.528895378112793,-5.13922119140625,-6.183318138122559,-5.530783176422119,-5.308929920196533,-5.7004714012146,-6.053252220153809,-5.563735485076904,-6.273633003234863,-6.559990406036377,-4.0843892097473145,-6.772822856903076,-5.496373653411865,-5.387583255767822,-6.265588760375977,-4.08669900894165,-5.049618721008301,-6.185205936431885,-5.5920820236206055,-5.873116493225098,-4.819058418273926,-4.929870128631592,-6.236239910125732,-6.18095588684082,-6.234452247619629,-4.2477312088012695,-5.974016189575195,-6.3717780113220215,-4.679630279541016,-5.288517951965332,-5.216290473937988,-6.161468982696533,-5.047900676727295,-5.275083065032959,-4.746511936187744,-4.969201564788818,-5.402195453643799,-5.335000038146973,-5.854090690612793,-5.654438018798828,-5.041797161102295,-5.270432472229004,-4.851434230804443,-5.712462425231934,-5.775331497192383,-5.606128692626953,-5.117011547088623,-6.293584823608398,-5.356616973876953,-4.941466331481934,-5.949162006378174,-4.714179039001465,-5.234983921051025,-5.850681304931641,-5.5193071365356445,-5.397138595581055,-5.029696464538574,-5.573114395141602,-4.65479850769043,-6.096044063568115,-5.340102672576904,-5.464972972869873,-6.423630714416504,-5.9784255027771,-5.326578140258789,-5.439119338989258,-5.596787452697754,-5.305296897888184,-4.6711106300354,-5.473764896392822,-5.17287015914917,-4.730599403381348,-5.1418657302856445,-5.718680381774902,-5.713038921356201,-4.401334762573242,-6.398741722106934,-3.9634509086608887,-4.452395915985107,-5.568471431732178,-5.589285850524902,-5.219752311706543,-4.912606716156006,-5.502899646759033,-5.81412410736084,-6.076737880706787,-6.293636798858643,-5.116075038909912,-5.719602584838867,-5.090619087219238,-5.60156774520874,-6.04959774017334,-3.7307028770446777,-5.339238166809082,-5.474489212036133,-5.036327362060547,-6.1796650886535645,-5.447934150695801,-4.137929916381836,-6.075428009033203,-6.098238945007324,-5.678464412689209,-4.8243303298950195,-5.1723246574401855,-6.003303050994873,-5.48507022857666,-5.526215553283691,-6.480190277099609,-6.539205551147461,-5.6678924560546875,-5.954273700714111,-5.603193283081055,-5.185120582580566,-5.690211772918701,-5.57891845703125,-5.050783157348633,-5.441473960876465,-5.731297016143799,-5.392122268676758,-5.413181304931641,-5.006068706512451,-6.861274242401123,-5.36255407333374,-6.2831034660339355,-5.84762716293335,-5.815194129943848,-5.372671604156494,-5.311596870422363,-5.742543697357178,-5.650458335876465,-5.792514324188232,-5.372308254241943,-5.450221538543701,-5.706465721130371,-5.205440044403076,-5.230306625366211,-5.312855243682861,-5.513335227966309,-5.639489650726318,-5.335122108459473,-5.745950698852539,-5.5245184898376465,-5.391866207122803,-5.904212474822998,-5.728081226348877,-4.852088451385498,-5.444051265716553,-5.537744522094727,-5.369645595550537,-5.269660949707031,-5.213024139404297,-5.487154006958008,-4.963733196258545,-5.531641960144043,-5.7254557609558105,-5.65606689453125,-5.481717586517334,-5.312532424926758,-5.56707763671875,-5.488705158233643,-5.357557773590088,-5.7238054275512695,-5.418074607849121],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"#AB63FA","size":3},"mode":"markers","name":"cluster 3","x":[-19.731082916259766,-22.38245964050293,-19.789838790893555,-19.683073043823242,-19.74149513244629,-19.675376892089844,-20.366039276123047,-21.17650604248047,-20.592819213867188,-19.832876205444336,-20.535539627075195,-21.04725456237793,-21.08646011352539,-20.559391021728516,-19.864805221557617,-20.096866607666016,-20.921600341796875,-19.674131393432617,-19.18958854675293,-20.692596435546875,-19.979618072509766,-21.066997528076172,-22.100189208984375,-21.997873306274414,-21.03421974182129,-20.001432418823242,-19.961034774780273,-21.753202438354492,-21.268415451049805,-21.618114471435547,-18.802940368652344,-20.077133178710938,-21.004079818725586,-21.624454498291016,-20.085052490234375,-21.00869369506836,-21.049442291259766,-21.397920608520508,-18.85047149658203,-21.86111068725586,-21.2210693359375,-21.176755905151367,-21.195297241210938,-20.88426399230957,-20.058216094970703,-20.22893714904785,-20.46788215637207,-20.205896377563477,-19.816471099853516,-20.500337600708008,-20.30000877380371,-21.451763153076172,-19.48648452758789,-20.963388442993164,-21.808746337890625,-20.532087326049805,-20.80862045288086,-21.596349716186523,-21.115619659423828,-19.97161293029785,-20.96674156188965,-20.73948860168457,-22.106048583984375,-21.088409423828125,-21.230060577392578,-20.48041343688965,-20.321739196777344,-21.472200393676758,-21.41373634338379,-21.064416885375977,-19.575275421142578,-20.822986602783203,-19.21134376525879,-20.412229537963867,-21.320608139038086,-20.435728073120117,-22.00689125061035,-20.22583770751953,-20.74637222290039,-20.488994598388672,-20.623746871948242,-20.702301025390625,-19.801729202270508,-20.238113403320312,-20.202194213867188,-19.774267196655273,-21.165733337402344,-22.05877113342285,-22.477970123291016,-21.338735580444336,-19.479013442993164,-20.095603942871094,-21.16917610168457,-20.405717849731445,-20.602313995361328,-20.543054580688477,-20.764469146728516,-21.301387786865234,-21.123981475830078,-21.450740814208984,-20.75960350036621,-20.844829559326172,-19.8469181060791,-19.926132202148438,-20.810720443725586,-19.961029052734375,-20.24656867980957,-21.183332443237305,-20.614614486694336,-20.604440689086914,-20.75160789489746,-18.765493392944336,-20.492979049682617,-21.120288848876953,-20.62491798400879,-20.718097686767578,-21.40839195251465,-20.730989456176758,-20.364768981933594,-20.830127716064453,-20.477155685424805,-20.392818450927734,-20.12152862548828,-19.792428970336914,-21.03192710876465,-20.459413528442383,-19.98517417907715,-20.95758628845215,-21.06414222717285,-20.02515983581543,-20.3040714263916,-20.328922271728516,-21.269222259521484,-20.32646369934082,-21.64946937561035,-20.309467315673828,-21.282493591308594,-20.633127212524414,-20.423585891723633,-20.572891235351562,-20.760005950927734,-20.989643096923828,-20.22769546508789,-20.56608772277832,-19.971647262573242,-19.406879425048828,-20.411863327026367,-20.60555076599121,-20.956680297851562,-20.388235092163086,-19.017505645751953,-20.506145477294922,-20.3170108795166,-21.14582061767578,-20.77361297607422,-19.794490814208984,-21.004409790039062,-20.698843002319336,-20.475818634033203,-20.47801399230957,-20.141456604003906,-21.215120315551758,-20.777963638305664,-20.719802856445312,-19.80467414855957,-19.96698570251465,-20.77224349975586,-20.536876678466797,-20.62819480895996,-20.387353897094727,-19.92801856994629,-19.849042892456055,-20.59773826599121,-20.58018684387207,-20.672107696533203,-20.406442642211914,-20.28687858581543,-20.16901206970215,-21.39153289794922,-20.60000991821289,-20.336374282836914,-20.455677032470703,-20.390304565429688,-20.75653648376465,-20.717220306396484,-20.687744140625,-20.826465606689453,-20.72105598449707,-20.666786193847656,-20.704130172729492,-20.710485458374023,-20.5435848236084,-20.198575973510742,-20.362884521484375,-20.34478187561035,-20.63017463684082,-20.880491256713867,-19.84199333190918,-20.83553123474121,-20.40234375,-20.558467864990234,-20.343921661376953,-20.69133186340332,-20.711841583251953,-20.685388565063477,-20.67680549621582,-20.50754165649414,-20.523107528686523,-20.637577056884766,-20.490556716918945,-20.57921600341797,-20.744033813476562,-20.560348510742188,-20.436569213867188,-20.7112979888916,-20.831663131713867,-20.764636993408203,-20.64147186279297,-20.525894165039062,-20.596277236938477,-20.27511215209961,-20.51163673400879,-20.694475173950195,-21.466848373413086,-20.63806915283203,-20.739145278930664,-20.664907455444336,-20.72491455078125,-20.8062801361084,-20.57762908935547,-20.809932708740234,-20.333662033081055,-20.885297775268555,-20.308382034301758,-20.54722785949707,-20.591360092163086,-20.52828598022461,-20.639307022094727,-20.778064727783203,-20.542238235473633,-20.51249122619629,-20.694673538208008,-20.779468536376953,-20.629486083984375,-20.527889251708984,-20.819477081298828,-20.629863739013672,-20.456083297729492,-20.614286422729492,-20.75467872619629],"y":[7.226347923278809,8.104235649108887,9.033217430114746,8.619539260864258,10.316058158874512,7.357335090637207,10.236699104309082,8.87075138092041,9.26149845123291,9.665105819702148,9.729555130004883,9.440858840942383,7.44549560546875,8.755596160888672,8.775742530822754,7.837094783782959,6.805335521697998,8.007126808166504,9.069034576416016,8.833173751831055,8.978630065917969,8.196060180664062,8.103081703186035,10.500894546508789,7.369081497192383,8.570425987243652,9.648719787597656,8.903018951416016,9.204081535339355,7.612142086029053,7.631712436676025,8.407816886901855,9.105984687805176,10.30273723602295,10.66319465637207,8.657126426696777,9.46812629699707,10.130621910095215,8.641464233398438,7.595956325531006,9.295832633972168,8.378538131713867,8.745247840881348,9.622722625732422,9.176819801330566,9.165411949157715,10.17850399017334,8.742300033569336,9.29708194732666,9.515795707702637,9.496200561523438,9.855558395385742,10.273195266723633,8.791254043579102,10.121352195739746,9.465758323669434,9.563578605651855,9.3624267578125,8.044997215270996,8.369465827941895,9.018966674804688,9.092660903930664,10.69743537902832,8.241719245910645,10.16899299621582,10.053014755249023,8.90282917022705,8.850278854370117,9.264252662658691,7.216431617736816,8.228232383728027,9.61838436126709,9.213205337524414,9.141987800598145,8.73296070098877,9.260125160217285,10.168309211730957,9.247827529907227,9.517373085021973,9.486605644226074,9.989277839660645,9.985631942749023,10.070286750793457,8.352104187011719,8.59418773651123,10.661940574645996,8.820965766906738,9.94298267364502,7.541391372680664,8.202345848083496,9.594078063964844,10.041165351867676,9.363113403320312,9.001022338867188,8.911073684692383,9.86727237701416,9.57371711730957,9.146712303161621,9.256174087524414,8.286968231201172,8.50069808959961,9.597248077392578,9.032942771911621,9.183785438537598,9.542243957519531,9.032093048095703,8.375314712524414,10.6718111038208,9.118300437927246,8.144512176513672,8.733291625976562,7.677799701690674,9.147794723510742,8.92497444152832,8.861501693725586,9.725566864013672,10.06501293182373,9.733532905578613,8.722537994384766,8.937151908874512,7.594668388366699,9.293803215026855,10.81201171875,9.40477466583252,9.136399269104004,9.836723327636719,8.057657241821289,9.444192886352539,9.065499305725098,8.58248519897461,9.634801864624023,8.650278091430664,6.744237422943115,7.967889785766602,10.09990406036377,10.385737419128418,9.638261795043945,9.15112018585205,8.950498580932617,8.676064491271973,9.27053165435791,9.112385749816895,9.518973350524902,9.7963228225708,7.978214740753174,9.233514785766602,9.50391960144043,8.115123748779297,9.607251167297363,8.909035682678223,9.564841270446777,9.170310020446777,8.286345481872559,9.708307266235352,9.19487190246582,9.571429252624512,9.064620971679688,9.192028999328613,9.515613555908203,8.691017150878906,9.392646789550781,9.95113754272461,9.655826568603516,9.638477325439453,7.51640510559082,8.519182205200195,8.151068687438965,9.423710823059082,9.126202583312988,10.218196868896484,8.587886810302734,9.189803123474121,8.997472763061523,9.408788681030273,9.411267280578613,9.003954887390137,9.068803787231445,8.57654094696045,8.376411437988281,9.528251647949219,8.35820198059082,9.478812217712402,8.797242164611816,9.614171028137207,9.733089447021484,9.001914024353027,9.173797607421875,8.723958969116211,8.869477272033691,8.975625038146973,9.414525032043457,9.279623985290527,8.496407508850098,9.249917984008789,9.063138961791992,9.679549217224121,8.813994407653809,8.859631538391113,9.519790649414062,8.883431434631348,9.174912452697754,9.009246826171875,9.228202819824219,8.910329818725586,9.408000946044922,8.801340103149414,8.898140907287598,9.389059066772461,8.950972557067871,8.597966194152832,8.563261032104492,9.343417167663574,9.270484924316406,9.115826606750488,8.507081031799316,9.367959976196289,9.266206741333008,9.049388885498047,9.116264343261719,9.200115203857422,8.93225383758545,8.923412322998047,8.85167121887207,8.784868240356445,9.191920280456543,9.33290958404541,9.253369331359863,8.881270408630371,9.102346420288086,9.193692207336426,8.802395820617676,9.191869735717773,8.88604736328125,8.971256256103516,8.956252098083496,8.893634796142578,9.103275299072266,9.151788711547852,9.27951717376709,9.156179428100586,9.167258262634277,8.868560791015625,9.240450859069824,9.10138988494873,9.154092788696289,9.017655372619629,9.595831871032715,9.112775802612305,9.138504981994629,8.703923225402832],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"#FFA15A","size":3},"mode":"markers","name":"cluster 4","x":[-9.175100326538086,-10.716907501220703,-10.726874351501465,-9.815886497497559,-9.400250434875488,-10.62441349029541,-7.344122409820557,-9.54061222076416,-10.116421699523926,-8.301437377929688,-11.397050857543945,-8.975103378295898,-10.076102256774902,-9.324216842651367,-9.985421180725098,-10.750006675720215,-8.627120018005371,-10.777556419372559,-11.10435962677002,-9.095454216003418,-10.007133483886719,-10.067122459411621,-9.367341041564941,-10.208551406860352,-9.062188148498535,-10.099392890930176,-11.50991153717041,-12.310323715209961,-9.73578929901123,-8.783028602600098,-7.7662458419799805,-9.940951347351074,-9.10755443572998,-9.453938484191895,-9.344366073608398,-10.368194580078125,-8.761310577392578,-10.37009334564209,-8.494026184082031,-7.931295871734619,-9.432374954223633,-9.199310302734375,-9.249691009521484,-10.741416931152344,-6.975325584411621,-10.181041717529297,-9.186158180236816,-9.125078201293945,-9.966309547424316,-10.896998405456543,-9.926901817321777,-8.77364444732666,-11.032240867614746,-10.546788215637207,-9.178365707397461,-9.000394821166992,-10.037184715270996,-9.1764554977417,-9.406737327575684,-9.083206176757812,-10.917478561401367,-9.886030197143555,-9.920478820800781,-10.46277141571045,-9.785969734191895,-9.214327812194824,-10.619718551635742,-10.524287223815918,-8.867352485656738,-8.840475082397461,-9.673160552978516,-9.955704689025879,-9.03779411315918,-9.119434356689453,-8.322237968444824,-9.366148948669434,-9.719332695007324,-10.583232879638672,-13.029067993164062,-9.35619831085205,-9.234796524047852,-9.609435081481934,-9.220083236694336,-9.26039981842041,-9.712023735046387,-11.550233840942383,-12.41116714477539,-9.396222114562988,-10.41490364074707,-9.366673469543457,-9.511944770812988,-10.430280685424805,-9.927976608276367,-10.242878913879395,-9.6993989944458,-9.116860389709473,-8.766212463378906,-9.140471458435059,-8.851835250854492,-9.544793128967285,-10.018913269042969,-10.519174575805664,-9.625988006591797,-8.505095481872559,-9.855740547180176,-9.025830268859863,-8.284582138061523,-9.05695915222168,-9.135666847229004,-9.563314437866211,-10.735196113586426,-9.237994194030762,-8.629672050476074,-10.032825469970703,-9.254179954528809,-9.54594898223877,-9.08013916015625,-10.205679893493652,-10.05886173248291,-10.071508407592773,-9.798309326171875,-9.809744834899902,-9.3975191116333,-9.490707397460938,-10.13472843170166,-9.934943199157715,-9.747115135192871,-9.910721778869629,-9.540874481201172,-9.56183910369873,-10.610647201538086,-9.106080055236816,-10.239164352416992,-9.618350982666016,-10.120057106018066,-9.479246139526367,-9.410802841186523,-9.344642639160156,-10.603217124938965,-9.857659339904785,-9.651808738708496,-9.790458679199219,-9.613485336303711,-8.753429412841797,-9.814496994018555,-10.036874771118164,-9.087752342224121,-10.086953163146973,-10.012587547302246,-9.581509590148926,-8.895777702331543,-9.217394828796387,-9.527303695678711,-9.137199401855469,-9.382330894470215,-8.648263931274414,-9.50781536102295,-9.926426887512207,-9.635238647460938,-8.721921920776367,-9.50088882446289,-9.291630744934082,-9.131155014038086,-9.215456008911133,-10.339070320129395,-10.079187393188477,-9.27904224395752,-9.018728256225586,-10.05575942993164,-10.040545463562012,-9.470974922180176,-9.823139190673828,-9.890298843383789,-9.765120506286621,-9.348893165588379,-9.688057899475098,-8.818222999572754,-8.987919807434082,-9.901732444763184,-9.591936111450195,-9.50507640838623,-9.660930633544922,-9.68260383605957,-9.728524208068848,-10.285073280334473,-9.63068962097168,-9.512048721313477,-10.065714836120605,-9.741775512695312,-9.478682518005371,-9.732453346252441,-9.622611045837402,-9.342430114746094,-9.70829963684082,-9.499640464782715,-9.671965599060059,-9.004505157470703,-9.380928993225098,-10.186408042907715,-9.355117797851562,-9.316676139831543,-9.157170295715332,-9.442183494567871,-9.637862205505371,-9.401167869567871,-9.710651397705078,-9.362649917602539,-9.573434829711914,-9.921152114868164,-10.042287826538086,-9.849603652954102,-9.761045455932617,-9.615523338317871,-9.695103645324707,-9.586164474487305,-9.896744728088379,-9.528752326965332,-9.726773262023926,-9.816180229187012,-9.5851411819458,-9.38146686553955,-9.749384880065918,-9.657855987548828,-9.518509864807129,-9.74229621887207,-9.72342586517334,-9.71842098236084,-9.483772277832031,-9.797788619995117,-9.688323974609375,-9.538456916809082,-9.60282039642334,-9.856755256652832,-9.03917121887207,-9.582382202148438,-9.78902530670166,-9.568499565124512,-9.978431701660156,-9.486825942993164,-9.960480690002441,-9.95223331451416,-9.556676864624023,-9.660000801086426,-9.885618209838867,-9.766162872314453,-9.544059753417969,-9.680782318115234,-9.638301849365234,-9.543113708496094,-9.835493087768555],"y":[23.71005630493164,24.434946060180664,24.7990665435791,25.16131591796875,23.18424415588379,25.865015029907227,23.700353622436523,24.260761260986328,25.27256965637207,25.488924026489258,25.38631248474121,24.6440372467041,23.544292449951172,24.583459854125977,24.50491714477539,24.193857192993164,26.018604278564453,24.958282470703125,22.140544891357422,25.143495559692383,24.255949020385742,24.985139846801758,24.62743377685547,24.735111236572266,25.36219024658203,24.87854766845703,24.236425399780273,24.644018173217773,25.20848846435547,23.361310958862305,26.687362670898438,24.555564880371094,24.602924346923828,24.475061416625977,23.210617065429688,25.330406188964844,24.719011306762695,24.235200881958008,23.11083221435547,25.520292282104492,23.07254409790039,22.955169677734375,25.003313064575195,24.363290786743164,24.05109214782715,24.255617141723633,26.04904556274414,23.772348403930664,23.859418869018555,25.401287078857422,24.5909423828125,25.852848052978516,22.828916549682617,24.948514938354492,24.992891311645508,22.929244995117188,25.512107849121094,23.80311393737793,24.839462280273438,25.699600219726562,24.464555740356445,25.499780654907227,24.68043327331543,24.882686614990234,23.810190200805664,24.140758514404297,25.39373016357422,24.347410202026367,23.202136993408203,24.59684944152832,25.90167808532715,25.97957992553711,24.573381423950195,25.441829681396484,22.616294860839844,23.014955520629883,24.44513511657715,23.308753967285156,23.606128692626953,24.05533790588379,26.398555755615234,24.89359474182129,24.533802032470703,23.951757431030273,24.03046417236328,23.929216384887695,23.567264556884766,25.64837646484375,22.922143936157227,23.52313804626465,25.096357345581055,25.30131721496582,24.090757369995117,25.066368103027344,24.553146362304688,25.137805938720703,23.910133361816406,24.781591415405273,23.84627342224121,24.872146606445312,25.397186279296875,24.57590103149414,24.203405380249023,23.892047882080078,24.9432373046875,22.331579208374023,23.626291275024414,24.326519012451172,24.60196304321289,24.273866653442383,24.28462028503418,24.876590728759766,24.693378448486328,24.37127685546875,24.944883346557617,24.648347854614258,23.664215087890625,24.59265899658203,22.996437072753906,24.077856063842773,24.72673988342285,23.809951782226562,24.9081974029541,24.9793758392334,24.970949172973633,24.284648895263672,24.2022762298584,23.795297622680664,22.956127166748047,23.945980072021484,23.901756286621094,24.955827713012695,24.566171646118164,23.570802688598633,25.16583251953125,24.882144927978516,24.69062042236328,24.271867752075195,23.925127029418945,24.469219207763672,24.466550827026367,24.942550659179688,24.178647994995117,24.26386070251465,24.602840423583984,23.36650848388672,25.246816635131836,25.26300621032715,24.687702178955078,26.56385612487793,25.162532806396484,24.6497859954834,23.867633819580078,25.09109115600586,25.197996139526367,24.6021785736084,25.678621292114258,24.3225040435791,24.67591094970703,27.065052032470703,24.59858512878418,23.705337524414062,24.22926139831543,25.086965560913086,24.69145965576172,24.300960540771484,24.198423385620117,24.285240173339844,24.340286254882812,24.9720401763916,24.561065673828125,24.67360496520996,24.49479866027832,24.543243408203125,24.612186431884766,24.580936431884766,24.241348266601562,25.481952667236328,24.409841537475586,24.89671516418457,24.61168098449707,23.794567108154297,25.636043548583984,24.808198928833008,24.5532283782959,25.59581184387207,24.712881088256836,24.81939125061035,24.68113899230957,24.427391052246094,24.679073333740234,24.730823516845703,24.060043334960938,25.1190242767334,24.605194091796875,24.735774993896484,24.477445602416992,25.033262252807617,24.775474548339844,24.8116512298584,24.065353393554688,24.753053665161133,24.515722274780273,24.385791778564453,24.820634841918945,24.635459899902344,24.335969924926758,24.22386932373047,24.522226333618164,24.351804733276367,23.74639320373535,24.62469482421875,24.571989059448242,24.232967376708984,24.353113174438477,24.0767765045166,24.219167709350586,24.660064697265625,24.597347259521484,24.306533813476562,24.382244110107422,24.363121032714844,24.340511322021484,24.71736717224121,24.296337127685547,24.423919677734375,23.8426570892334,24.50372886657715,24.41991424560547,24.547208786010742,24.302461624145508,24.126386642456055,24.574922561645508,24.362939834594727,24.6966609954834,24.598400115966797,24.416542053222656,24.493196487426758,24.693058013916016,24.65599822998047,24.27741050720215,24.430294036865234,24.615015029907227,24.422578811645508,24.249420166015625,24.414793014526367,24.298206329345703,24.337114334106445,24.375808715820312,24.31322479248047],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"#19D3F3","size":3},"mode":"markers","name":"cluster 5","x":[24.910682678222656,25.348167419433594,25.48988151550293,25.407487869262695,25.732444763183594,23.847015380859375,22.813661575317383,23.38425636291504,25.381792068481445,25.977720260620117,23.921180725097656,25.459186553955078,25.44654655456543,23.869754791259766,23.65787696838379,24.63576316833496,24.070219039916992,24.41889762878418,26.159875869750977,23.499589920043945,23.049659729003906,24.817663192749023,26.21938705444336,26.0670108795166,26.25128173828125,26.47380828857422,24.570749282836914,23.519840240478516,24.205509185791016,23.855426788330078,24.962203979492188,23.670520782470703,25.89510154724121,25.836151123046875,25.047039031982422,24.668333053588867,25.35805892944336,23.431467056274414,24.889062881469727,24.470182418823242,25.644718170166016,24.241649627685547,25.642086029052734,24.739887237548828,26.86212730407715,26.087919235229492,24.986738204956055,24.29734992980957,25.399991989135742,25.015504837036133,25.877485275268555,24.436172485351562,23.89093589782715,24.6669864654541,25.35089111328125,25.90843963623047,25.37848472595215,24.64467430114746,22.98560333251953,23.284969329833984,24.967267990112305,24.69975471496582,23.997577667236328,26.68948745727539,24.033126831054688,24.847068786621094,24.163692474365234,25.16253662109375,25.43760108947754,25.578535079956055,24.522985458374023,24.069684982299805,24.80597686767578,25.665630340576172,25.82100486755371,26.08856964111328,24.920940399169922,24.668107986450195,24.812049865722656,24.51218032836914,23.88321304321289,26.501018524169922,26.270427703857422,24.104711532592773,25.693885803222656,25.181488037109375,24.676055908203125,24.59322166442871,24.386714935302734,25.93047332763672,25.701984405517578,24.26602554321289,24.1798038482666,24.381935119628906,24.643356323242188,23.678293228149414,23.199356079101562,23.61591148376465,24.427433013916016,24.917470932006836,24.892045974731445,23.972444534301758,26.088579177856445,24.547359466552734,24.9840030670166,24.180889129638672,24.984189987182617,25.684551239013672,24.167797088623047,24.696142196655273,25.695602416992188,25.066173553466797,25.667423248291016,25.642000198364258,25.22545051574707,24.998003005981445,25.02340316772461,23.623432159423828,24.290231704711914,23.941911697387695,24.080957412719727,24.83702850341797,25.142223358154297,25.341718673706055,24.901973724365234,24.798099517822266,24.78040885925293,25.274559020996094,25.017114639282227,25.29698944091797,25.75497055053711,24.743593215942383,24.934101104736328,22.918476104736328,23.8627986907959,25.041152954101562,24.40079689025879,25.08211326599121,25.03680419921875,25.251964569091797,26.824872970581055,25.268795013427734,25.38536834716797,24.15636444091797,25.148794174194336,26.042984008789062,25.058656692504883,24.967531204223633,25.504398345947266,26.26141929626465,25.03709602355957,25.296966552734375,24.482267379760742,25.098953247070312,25.136871337890625,25.20359992980957,24.501789093017578,25.006486892700195,25.160280227661133,24.87706756591797,25.356412887573242,24.84685707092285,24.532569885253906,25.408498764038086,24.9771728515625,23.786928176879883,25.272716522216797,25.086551666259766,25.314998626708984,25.574298858642578,24.647024154663086,24.610776901245117,25.17986297607422,24.30775260925293,24.306135177612305,24.84845733642578,23.967309951782227,25.250280380249023,25.262104034423828,25.268165588378906,24.376819610595703,24.788846969604492,24.808883666992188,25.938684463500977,24.916746139526367,25.148916244506836,24.283063888549805,23.665111541748047,25.89096450805664,24.367918014526367,24.964149475097656,25.167160034179688,25.62744140625,24.95513153076172,24.773771286010742,25.032804489135742,25.15969467163086,22.504192352294922,24.33920669555664,24.548091888427734,25.127111434936523,25.07375717163086,24.864395141601562,24.53053092956543,24.667316436767578,24.535911560058594,24.702308654785156,25.148649215698242,24.254562377929688,24.9354190826416,23.8061580657959,24.985576629638672,24.732053756713867,24.903745651245117,25.011648178100586,24.93807029724121,25.720577239990234,24.046890258789062,24.719242095947266,24.302921295166016,25.196651458740234,25.012319564819336,25.0021915435791,24.866127014160156,25.13617706298828,24.783721923828125,26.20484161376953,24.779682159423828,25.24911117553711,25.198650360107422,24.801115036010742,25.046154022216797,24.449413299560547,24.317089080810547,24.401512145996094,25.125856399536133,26.171432495117188,24.532241821289062,24.47679901123047,25.24970817565918,24.755048751831055,24.753826141357422,24.841386795043945,25.167728424072266,24.661977767944336,25.060508728027344,24.429502487182617,24.954256057739258,23.826745986938477,24.808055877685547],"y":[3.330777645111084,6.019943714141846,4.861457347869873,2.84415340423584,3.5437655448913574,3.534959554672241,3.854865789413452,3.6172451972961426,3.4784069061279297,3.49247145652771,4.2546916007995605,3.9742183685302734,3.6750690937042236,3.236593008041382,6.464629173278809,4.957302570343018,3.328254222869873,3.1449062824249268,3.6362767219543457,3.9830832481384277,3.4315762519836426,2.0553534030914307,3.0896413326263428,4.786179065704346,2.4708950519561768,1.6898365020751953,2.7561004161834717,4.422569751739502,5.312889099121094,2.843686103820801,3.898256778717041,3.3802926540374756,3.081857919692993,2.549006700515747,6.568864822387695,1.8561350107192993,3.5219953060150146,4.028653621673584,4.867859840393066,3.298518419265747,2.912851572036743,2.8183648586273193,3.6120944023132324,3.2770588397979736,4.81455135345459,3.034832715988159,3.2831168174743652,3.4007396697998047,3.924490451812744,4.370161533355713,2.5357303619384766,3.819746255874634,4.093968391418457,4.128928184509277,3.7001116275787354,4.042128086090088,3.876143217086792,3.081054925918579,3.8087897300720215,3.9353036880493164,5.900588035583496,4.562702655792236,5.09755802154541,4.889177322387695,3.416018009185791,3.6303422451019287,2.641890048980713,2.152134418487549,3.349952220916748,2.3222546577453613,2.6651864051818848,4.539223670959473,4.1497297286987305,1.6451940536499023,2.82637357711792,2.9408631324768066,3.226947784423828,3.803784132003784,2.7109568119049072,3.7321364879608154,2.609877347946167,4.616680145263672,3.7110846042633057,3.902168035507202,3.286947250366211,2.775019645690918,2.888932704925537,4.100666046142578,3.6565377712249756,5.0195817947387695,3.8004181385040283,3.8139235973358154,3.004836320877075,4.7677717208862305,3.8818089962005615,3.8270537853240967,3.622887372970581,2.692537784576416,3.8510825634002686,3.7565150260925293,3.519717216491699,3.420626401901245,3.970449209213257,3.4709067344665527,3.741607666015625,4.763010025024414,2.6735899448394775,3.513038396835327,4.614933013916016,2.8562445640563965,2.980661392211914,2.744201898574829,4.365338325500488,4.760097503662109,3.569880485534668,4.1554412841796875,3.5923776626586914,4.546722412109375,3.211880683898926,3.9002840518951416,3.9789390563964844,3.5970873832702637,4.157991886138916,3.7178680896759033,3.418029546737671,3.920177936553955,4.259256362915039,3.2298507690429688,3.52191162109375,2.1080965995788574,4.146679401397705,3.8270671367645264,3.7885706424713135,4.3934712409973145,3.771980047225952,2.152224063873291,4.0874176025390625,3.792588472366333,3.299318790435791,2.886904239654541,4.443240165710449,3.076115608215332,2.786410093307495,4.446681976318359,3.3221421241760254,4.015493392944336,3.7783203125,4.631606578826904,3.8057150840759277,4.460583686828613,3.4362952709198,3.932455539703369,3.518686532974243,3.353119134902954,3.7304670810699463,3.748790979385376,3.7513513565063477,3.358006000518799,3.458204507827759,3.7707579135894775,3.6961021423339844,3.5182719230651855,2.735109329223633,3.5971291065216064,3.432581663131714,4.07050895690918,4.29788875579834,2.949314832687378,3.626476764678955,3.2394449710845947,3.838649272918701,3.7654170989990234,3.8896117210388184,3.830101490020752,4.4514851570129395,3.5939559936523438,3.9622817039489746,3.3246803283691406,3.969759702682495,3.900968074798584,4.015563488006592,3.4784393310546875,3.356776237487793,4.089617729187012,3.585742473602295,3.5050313472747803,3.545259714126587,7.427239418029785,3.277217388153076,3.6106390953063965,3.5076332092285156,3.693650722503662,4.113780975341797,4.582255840301514,3.250608205795288,3.2966461181640625,3.6085402965545654,4.6655964851379395,4.20128870010376,3.6117734909057617,3.3306725025177,3.6887853145599365,3.5095701217651367,3.677093267440796,3.716674566268921,3.943042755126953,3.4887824058532715,3.740898847579956,3.957815408706665,3.2310473918914795,4.098201274871826,3.6408519744873047,3.6249303817749023,3.524247646331787,3.3207461833953857,3.4133565425872803,4.97858190536499,4.026023864746094,3.5367562770843506,4.091683864593506,3.728238105773926,3.69111704826355,3.712973117828369,3.7348504066467285,3.814938545227051,3.5878329277038574,4.956797122955322,3.7523672580718994,4.050398349761963,3.9145822525024414,3.5911078453063965,3.399374485015869,3.8401505947113037,3.9698643684387207,3.6713316440582275,4.1900482177734375,4.435842990875244,4.2473626136779785,3.996246814727783,3.4805426597595215,3.6318531036376953,3.868190288543701,3.6766669750213623,3.653940200805664,3.8563899993896484,3.699369430541992,3.8119192123413086,3.957099676132202,3.7662651538848877,4.227260112762451],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"}],                        {"template":{"data":{"scatter":[{"marker":{"color":"#d92310"},"type":"scatter"}]},"layout":{"height":576,"paper_bgcolor":"#fcfcfc","plot_bgcolor":"#fcfcfc","width":1024}},"xaxis":{"zeroline":false},"yaxis":{"zeroline":false}},                        {"responsive": true}                    ).then(function(){
                            
var gd = document.getElementById('a11bb9b5-89e3-4ba7-9e87-382a817512e4');
var x = new MutationObserver(function (mutations, observer) {{
        var display = window.getComputedStyle(gd).display;
        if (!display || display === 'none') {{
            console.log([gd, 'removed!']);
            Plotly.purge(gd);
            observer.disconnect();
        }}
}});

// Listen for the removal of the full notebook cells
var notebookContainer = gd.closest('#notebook-container');
if (notebookContainer) {{
    x.observe(notebookContainer, {childList: true});
}}

// Listen for the clearing of the current output cell
var outputEl = gd.closest('.output');
if (outputEl) {{
    x.observe(outputEl, {childList: true});
}}

                        })                };                });            </script>        </div>
</div>
</div>
<p>Let’s encapsulate the algorithm so we can run it for multiple iterations.</p>
<div id="5bbca286" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb23" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb23-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> update(X):</span>
<span id="cb23-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, x <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(X):</span>
<span id="cb23-3">      dist <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> X).square().<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).sqrt()</span>
<span id="cb23-4">      ws <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> gauss_kernel(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>dist, mean<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, std<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>bw)</span>
<span id="cb23-5">      X[i] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (ws[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> X).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> ws.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>()</span>
<span id="cb23-6"></span>
<span id="cb23-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> meanshift(data):</span>
<span id="cb23-8">   X <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> data.clone()</span>
<span id="cb23-9">   <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>): update(X)</span>
<span id="cb23-10">   <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> X</span></code></pre></div></div>
</div>
<div id="4170ffa4" class="cell page-columns page-full">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb24" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb24-1">plot_data(centroids<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, meanshift(data), n_samples)</span></code></pre></div></div>
<div class="cell-output cell-output-display column-page">
<div>                            <div id="549d3d93-edec-4655-a542-29441f8df229" class="plotly-graph-div" style="height:576px; width:1024px;"></div>            <script type="text/javascript">                require(["plotly"], function(Plotly) {                    window.PLOTLYENV=window.PLOTLYENV || {};                                    if (document.getElementById("549d3d93-edec-4655-a542-29441f8df229")) {                    Plotly.newPlot(                        "549d3d93-edec-4655-a542-29441f8df229",                        [{"marker":{"color":"#636EFA","size":3},"mode":"markers","name":"cluster 0","x":[2.578917980194092,2.578918218612671,2.578918218612671,2.57891845703125,2.57891845703125,2.578918218612671,2.578918218612671,2.578917980194092,2.578917980194092,2.5789175033569336,2.5789172649383545,2.5789170265197754,2.578916311264038,2.57891583442688,2.5789151191711426,2.5789146423339844,2.578914165496826,2.5789132118225098,2.5789127349853516,2.5789120197296143,2.578911304473877,2.5789103507995605,2.578909397125244,2.5789084434509277,2.5789074897766113,2.578906774520874,2.5789058208465576,2.578904867172241,2.578903913497925,2.5789027214050293,2.578901767730713,2.5789008140563965,2.578899621963501,2.5788986682891846,2.578897476196289,2.5788967609405518,2.5788955688476562,2.5788943767547607,2.5788931846618652,2.578892230987549,2.5788910388946533,2.578890085220337,2.5788888931274414,2.578887701034546,2.5788867473602295,2.578885555267334,2.5788843631744385,2.578883647918701,2.5788824558258057,2.57888126373291,2.5788803100585938,2.5788793563842773,2.578878402709961,2.5788774490356445,2.578876495361328,2.5788755416870117,2.5788745880126953,2.578873634338379,2.5788726806640625,2.578871726989746,2.5788707733154297,2.5788698196411133,2.578868865966797,2.5788681507110596,2.578867197036743,2.578866481781006,2.5788657665252686,2.5788650512695312,2.5788638591766357,2.5788631439208984,2.578862428665161,2.578861713409424,2.5788609981536865,2.57886004447937,2.578859329223633,2.5788588523864746,2.5788581371307373,2.578857421875,2.5788567066192627,2.5788562297821045,2.578855276107788,2.578854560852051,2.5788540840148926,2.5788533687591553,2.578852891921997,2.578852415084839,2.5788516998291016,2.5788512229919434,2.578850746154785,2.578850507736206,2.5788495540618896,2.5788493156433105,2.5788486003875732,2.578848361968994,2.578847885131836,2.5788474082946777,2.5788469314575195,2.5788464546203613,2.578845977783203,2.578845739364624,2.578845500946045,2.5788450241088867,2.5788445472717285,2.5788445472717285,2.5788443088531494,2.578843832015991,2.578843832015991,2.578843593597412,2.578843116760254,2.578843116760254,2.578843116760254,2.5788426399230957,2.5788426399230957,2.5788426399230957,2.5788426399230957,2.5788426399230957,2.5788426399230957,2.5788426399230957,2.5788426399230957,2.5788426399230957,2.5788426399230957,2.578843116760254,2.578843116760254,2.578843116760254,2.578843593597412,2.578843593597412,2.578843832015991,2.578843832015991,2.5788443088531494,2.5788445472717285,2.5788447856903076,2.578845262527466,2.578845500946045,2.578845500946045,2.578845739364624,2.5788462162017822,2.5788466930389404,2.5788469314575195,2.5788474082946777,2.578847646713257,2.578848123550415,2.5788486003875732,2.5788488388061523,2.5788493156433105,2.5788495540618896,2.578850030899048,2.578850507736206,2.5788509845733643,2.5788514614105225,2.5788519382476807,2.578852415084839,2.578852653503418,2.5788533687591553,2.5788536071777344,2.5788540840148926,2.5788543224334717,2.57885479927063,2.578855276107788,2.5788557529449463,2.5788562297821045,2.5788564682006836,2.578856945037842,2.578857183456421,2.578857660293579,2.5788581371307373,2.5788583755493164,2.5788588523864746,2.578859329223633,2.578859806060791,2.57886004447937,2.5788605213165283,2.5788609981536865,2.5788614749908447,2.578861951828003,2.578862190246582,2.5788626670837402,2.5788629055023193,2.5788631439208984,2.5788636207580566,2.5788638591766357,2.578864097595215,2.578864574432373,2.5788650512695312,2.5788652896881104,2.5788657665252686,2.5788660049438477,2.5788662433624268,2.578866720199585,2.578866958618164,2.578866958618164,2.578867197036743,2.5788676738739014,2.5788679122924805,2.5788679122924805,2.5788683891296387,2.578868865966797,2.578868865966797,2.578869104385376,2.578869342803955,2.578869581222534,2.5788698196411133,2.5788698196411133,2.5788700580596924,2.5788702964782715,2.5788705348968506,2.5788707733154297,2.5788707733154297,2.5788707733154297,2.5788707733154297,2.578871011734009,2.578871250152588,2.578871250152588,2.578871488571167,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871488571167,2.578871488571167,2.578871488571167,2.578871011734009,2.578871011734009,2.578871011734009,2.578871011734009,2.5788707733154297,2.5788707733154297,2.5788705348968506,2.5788702964782715,2.5788700580596924,2.5788698196411133,2.5788698196411133,2.578869581222534,2.578869342803955,2.578869342803955,2.578869104385376,2.578868865966797],"y":[-21.17802619934082,-21.178024291992188,-21.178024291992188,-21.178022384643555,-21.178020477294922,-21.17801856994629,-21.178016662597656,-21.178016662597656,-21.178016662597656,-21.17801284790039,-21.17801284790039,-21.178010940551758,-21.178010940551758,-21.178009033203125,-21.178009033203125,-21.178009033203125,-21.178007125854492,-21.17800521850586,-21.17800521850586,-21.17800521850586,-21.178003311157227,-21.178001403808594,-21.178001403808594,-21.178001403808594,-21.178001403808594,-21.17799949645996,-21.17799949645996,-21.177997589111328,-21.177995681762695,-21.177995681762695,-21.177995681762695,-21.177995681762695,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177995681762695,-21.177995681762695,-21.177995681762695,-21.177997589111328,-21.177997589111328,-21.17799949645996,-21.17799949645996,-21.17799949645996,-21.178001403808594,-21.178001403808594,-21.178001403808594,-21.178003311157227,-21.178003311157227,-21.17800521850586,-21.17800521850586,-21.17800521850586,-21.178007125854492,-21.178007125854492,-21.178009033203125,-21.178009033203125,-21.178009033203125,-21.178010940551758,-21.178010940551758,-21.178010940551758,-21.178014755249023,-21.178014755249023,-21.178014755249023,-21.178016662597656,-21.178016662597656,-21.178016662597656,-21.178016662597656,-21.178016662597656,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178022384643555,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.17802619934082,-21.17802619934082,-21.17802619934082,-21.178028106689453,-21.178030014038086,-21.178030014038086,-21.178030014038086,-21.178030014038086,-21.17803192138672,-21.17803192138672,-21.17803192138672,-21.17803382873535,-21.17803382873535,-21.17803382873535,-21.17803382873535,-21.17803382873535,-21.178035736083984,-21.178035736083984,-21.178035736083984,-21.178035736083984,-21.178035736083984,-21.178037643432617,-21.178037643432617,-21.178037643432617,-21.178037643432617,-21.178037643432617,-21.178037643432617,-21.17803955078125,-21.17803955078125,-21.17803955078125,-21.17803955078125,-21.17803955078125,-21.17803955078125,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.17803955078125,-21.17803955078125,-21.17803955078125,-21.17803955078125,-21.17803955078125,-21.17803955078125,-21.17803955078125,-21.178037643432617,-21.178037643432617,-21.178037643432617,-21.178037643432617,-21.178037643432617,-21.178035736083984,-21.178035736083984,-21.178035736083984,-21.178035736083984,-21.178035736083984,-21.17803382873535,-21.17803382873535,-21.17803192138672,-21.17803192138672,-21.17803192138672,-21.17803192138672,-21.17803192138672,-21.17803192138672,-21.17803192138672,-21.178030014038086,-21.178030014038086,-21.178030014038086,-21.178030014038086,-21.178030014038086,-21.178030014038086,-21.178030014038086,-21.178028106689453,-21.178028106689453,-21.17802619934082,-21.17802619934082,-21.17802619934082,-21.17802619934082,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178022384643555,-21.178022384643555,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"#EF553B","size":3},"mode":"markers","name":"cluster 1","x":[11.031108856201172,11.031103134155273,11.031098365783691,11.031094551086426,11.031089782714844,11.031085014343262,11.03108024597168,11.031076431274414,11.031071662902832,11.031067848205566,11.0310640335083,11.031060218811035,11.03105640411377,11.031052589416504,11.031049728393555,11.031046867370605,11.031044006347656,11.03104019165039,11.031037330627441,11.031034469604492,11.03103256225586,11.03102970123291,11.031028747558594,11.031024932861328,11.031023979187012,11.031021118164062,11.03101921081543,11.031017303466797,11.031015396118164,11.031013488769531,11.031012535095215,11.031010627746582,11.031009674072266,11.031007766723633,11.031005859375,11.031005859375,11.031003952026367,11.031002044677734,11.031001091003418,11.031001091003418,11.030999183654785,11.030999183654785,11.030998229980469,11.030998229980469,11.030996322631836,11.030996322631836,11.03099536895752,11.03099536895752,11.030994415283203,11.030994415283203,11.030994415283203,11.030994415283203,11.030994415283203,11.030994415283203,11.030994415283203,11.030994415283203,11.030994415283203,11.030994415283203,11.030994415283203,11.030994415283203,11.03099536895752,11.03099536895752,11.030996322631836,11.030996322631836,11.030996322631836,11.030996322631836,11.030997276306152,11.030998229980469,11.030998229980469,11.030999183654785,11.031000137329102,11.031000137329102,11.031001091003418,11.031002044677734,11.031002044677734,11.03100299835205,11.031003952026367,11.031004905700684,11.031005859375,11.031005859375,11.031007766723633,11.03100872039795,11.031009674072266,11.031009674072266,11.031010627746582,11.031011581420898,11.031013488769531,11.031014442443848,11.031014442443848,11.03101634979248,11.03101634979248,11.031017303466797,11.031017303466797,11.03101921081543,11.031020164489746,11.031021118164062,11.031022071838379,11.031023025512695,11.031023979187012,11.031024932861328,11.031025886535645,11.031026840209961,11.031028747558594,11.031028747558594,11.03102970123291,11.03102970123291,11.031031608581543,11.03103256225586,11.03103256225586,11.031034469604492,11.031034469604492,11.031036376953125,11.031037330627441,11.031037330627441,11.031039237976074,11.03104019165039,11.03104019165039,11.031042098999023,11.03104305267334,11.031044006347656,11.031044006347656,11.031045913696289,11.031046867370605,11.031046867370605,11.031047821044922,11.031047821044922,11.031049728393555,11.031051635742188,11.031051635742188,11.031052589416504,11.031052589416504,11.031054496765137,11.03105640411377,11.03105640411377,11.031057357788086,11.031057357788086,11.031059265136719,11.031059265136719,11.031060218811035,11.031062126159668,11.031063079833984,11.0310640335083,11.0310640335083,11.031064987182617,11.031065940856934,11.03106689453125,11.031067848205566,11.031067848205566,11.031068801879883,11.031070709228516,11.031071662902832,11.031071662902832,11.031072616577148,11.031072616577148,11.031073570251465,11.031074523925781,11.031075477600098,11.031075477600098,11.031076431274414,11.031076431274414,11.03107738494873,11.031078338623047,11.031079292297363,11.031079292297363,11.031079292297363,11.03108024597168,11.03108024597168,11.031081199645996,11.031081199645996,11.031081199645996,11.031082153320312,11.031082153320312,11.031083106994629,11.031083106994629,11.031083106994629,11.031083106994629,11.031083106994629,11.031084060668945,11.031084060668945,11.031084060668945,11.031084060668945,11.031084060668945,11.031084060668945,11.031084060668945,11.031084060668945,11.031084060668945,11.031084060668945,11.031084060668945,11.031083106994629,11.031083106994629,11.031083106994629,11.031083106994629,11.031083106994629,11.031083106994629,11.031083106994629,11.031082153320312,11.031082153320312,11.031082153320312,11.03108024597168,11.03108024597168,11.031079292297363,11.031079292297363,11.031078338623047,11.031078338623047,11.03107738494873,11.031076431274414,11.031075477600098,11.031075477600098,11.031073570251465,11.031072616577148,11.031071662902832,11.031071662902832,11.0310697555542,11.0310697555542,11.031067848205566,11.031067848205566,11.031065940856934,11.031064987182617,11.0310640335083,11.031063079833984,11.031063079833984,11.031061172485352,11.031060218811035,11.031060218811035,11.031059265136719,11.031058311462402,11.031057357788086,11.03105640411377,11.03105640411377,11.031055450439453,11.031054496765137,11.031054496765137,11.031052589416504,11.031052589416504,11.031052589416504,11.031051635742188,11.031050682067871,11.031050682067871,11.031049728393555,11.031049728393555,11.031047821044922,11.031047821044922,11.031047821044922,11.031047821044922,11.031047821044922,11.031046867370605,11.031046867370605,11.031046867370605,11.031044960021973,11.031044960021973],"y":[10.844741821289062,10.844743728637695,10.844746589660645,10.844747543334961,10.844749450683594,10.844751358032227,10.844752311706543,10.844754219055176,10.844755172729492,10.844757080078125,10.844758987426758,10.844759941101074,10.844762802124023,10.84476375579834,10.844765663146973,10.844766616821289,10.844768524169922,10.844770431518555,10.844771385192871,10.844773292541504,10.84477424621582,10.844775199890137,10.84477710723877,10.844778060913086,10.844779968261719,10.844781875610352,10.844782829284668,10.844782829284668,10.8447847366333,10.844785690307617,10.844786643981934,10.844788551330566,10.844789505004883,10.8447904586792,10.844792366027832,10.844793319702148,10.844794273376465,10.844796180725098,10.844797134399414,10.84479808807373,10.844799041748047,10.844799995422363,10.84480094909668,10.844802856445312,10.844803810119629,10.844804763793945,10.844805717468262,10.844806671142578,10.844807624816895,10.844808578491211,10.844810485839844,10.844810485839844,10.844812393188477,10.844813346862793,10.84481430053711,10.844815254211426,10.844816207885742,10.844817161560059,10.844817161560059,10.844818115234375,10.844819068908691,10.844820022583008,10.844820976257324,10.844820976257324,10.84482192993164,10.844822883605957,10.844822883605957,10.84482479095459,10.84482479095459,10.84482479095459,10.84482479095459,10.844825744628906,10.844826698303223,10.844826698303223,10.844827651977539,10.844828605651855,10.844828605651855,10.844828605651855,10.844828605651855,10.844828605651855,10.844830513000488,10.844830513000488,10.844830513000488,10.844831466674805,10.844831466674805,10.844831466674805,10.844831466674805,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844833374023438,10.844833374023438,10.844833374023438,10.844833374023438,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844831466674805,10.844831466674805,10.844831466674805,10.844831466674805,10.844830513000488,10.844830513000488,10.844829559326172,10.844828605651855,10.844828605651855,10.844828605651855,10.844828605651855,10.844828605651855,10.844827651977539,10.844827651977539,10.844826698303223,10.844825744628906,10.84482479095459,10.84482479095459,10.84482479095459,10.844823837280273,10.844822883605957,10.84482192993164,10.844820976257324,10.844820976257324,10.844820022583008,10.844819068908691,10.844818115234375,10.844818115234375,10.844818115234375,10.844817161560059,10.844817161560059,10.844815254211426,10.844813346862793,10.844813346862793,10.844812393188477,10.84481143951416,10.844810485839844,10.844809532165527,10.844808578491211,10.844808578491211,10.844807624816895,10.844806671142578,10.844805717468262,10.844804763793945,10.844804763793945,10.844802856445312,10.844801902770996,10.84480094909668,10.84480094909668,10.844799995422363,10.844799041748047,10.84479808807373,10.844797134399414,10.844797134399414,10.844796180725098,10.844795227050781,10.844794273376465,10.844793319702148,10.844793319702148,10.844793319702148,10.844792366027832,10.844791412353516,10.8447904586792,10.844789505004883,10.844789505004883,10.844789505004883,10.844789505004883,10.84478759765625,10.84478759765625,10.844785690307617,10.844785690307617,10.844785690307617,10.844785690307617,10.8447847366333,10.844783782958984,10.844783782958984,10.844783782958984,10.844782829284668,10.844782829284668,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844782829284668,10.844783782958984,10.8447847366333,10.8447847366333,10.8447847366333,10.844785690307617,10.844785690307617,10.844785690307617,10.84478759765625,10.84478759765625,10.844789505004883,10.844789505004883,10.8447904586792,10.8447904586792,10.8447904586792,10.844791412353516,10.844792366027832,10.844792366027832,10.844793319702148,10.844793319702148,10.844794273376465,10.844794273376465,10.844794273376465,10.844795227050781,10.844795227050781,10.844796180725098,10.844797134399414,10.844797134399414,10.844797134399414,10.844797134399414,10.844797134399414,10.84479808807373,10.84479808807373,10.84479808807373,10.844799041748047,10.844799995422363,10.84480094909668,10.84480094909668,10.84480094909668,10.84480094909668,10.84480094909668,10.844801902770996,10.844802856445312,10.844802856445312,10.844802856445312,10.844802856445312],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"#00CC96","size":3},"mode":"markers","name":"cluster 2","x":[-18.722532272338867,-18.7225284576416,-18.722524642944336,-18.722524642944336,-18.722524642944336,-18.722522735595703,-18.722518920898438,-18.722518920898438,-18.722515106201172,-18.72251319885254,-18.722511291503906,-18.722509384155273,-18.72250747680664,-18.722503662109375,-18.722503662109375,-18.72249984741211,-18.72249984741211,-18.722497940063477,-18.722497940063477,-18.72249412536621,-18.722492218017578,-18.722492218017578,-18.722488403320312,-18.722488403320312,-18.722488403320312,-18.722484588623047,-18.722484588623047,-18.722482681274414,-18.72247886657715,-18.72247886657715,-18.722476959228516,-18.722476959228516,-18.722476959228516,-18.72247314453125,-18.72247314453125,-18.72247314453125,-18.722471237182617,-18.722469329833984,-18.722469329833984,-18.722469329833984,-18.72246742248535,-18.72246742248535,-18.72246742248535,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.72246742248535,-18.72246742248535,-18.72246742248535,-18.722469329833984,-18.722469329833984,-18.722469329833984,-18.722469329833984,-18.722469329833984,-18.72247314453125,-18.72247314453125,-18.72247314453125,-18.72247314453125,-18.72247314453125,-18.72247314453125,-18.72247314453125,-18.722475051879883,-18.722476959228516,-18.722476959228516,-18.722476959228516,-18.722476959228516,-18.722476959228516,-18.72247886657715,-18.72247886657715,-18.72247886657715,-18.72247886657715,-18.72247886657715,-18.72247886657715,-18.72248077392578,-18.722482681274414,-18.722482681274414,-18.722482681274414,-18.722482681274414,-18.722484588623047,-18.722484588623047,-18.722484588623047,-18.722484588623047,-18.72248649597168,-18.722488403320312,-18.722488403320312,-18.722488403320312,-18.722488403320312,-18.722488403320312,-18.722488403320312,-18.722488403320312,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.72249412536621,-18.72249412536621,-18.72249412536621,-18.722496032714844,-18.722496032714844,-18.722497940063477,-18.722497940063477,-18.722497940063477,-18.722497940063477,-18.722497940063477,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722505569458008,-18.722505569458008,-18.722505569458008,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.722505569458008,-18.722505569458008,-18.722505569458008,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722501754760742,-18.722501754760742,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.722497940063477,-18.722497940063477,-18.722497940063477,-18.722497940063477,-18.722496032714844,-18.722496032714844,-18.722496032714844,-18.722496032714844,-18.722496032714844,-18.72249412536621,-18.72249412536621,-18.72249412536621,-18.72249412536621,-18.72249412536621,-18.72249412536621,-18.72249412536621,-18.72249412536621,-18.72249412536621,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722490310668945,-18.722490310668945],"y":[-5.475937366485596,-5.47593879699707,-5.475940227508545,-5.4759416580200195,-5.475942611694336,-5.4759440422058105,-5.475945949554443,-5.475946426391602,-5.475947856903076,-5.475949764251709,-5.475950717926025,-5.4759521484375,-5.475953578948975,-5.475954055786133,-5.475955486297607,-5.475956439971924,-5.47595739364624,-5.475959300994873,-5.475959777832031,-5.475960731506348,-5.475961685180664,-5.4759626388549805,-5.475963592529297,-5.475964069366455,-5.4759650230407715,-5.47596549987793,-5.475966453552246,-5.4759674072265625,-5.4759674072265625,-5.475968360900879,-5.475968837738037,-5.475969314575195,-5.475969314575195,-5.4759697914123535,-5.475970268249512,-5.47597074508667,-5.475971221923828,-5.475971221923828,-5.475971221923828,-5.475971221923828,-5.475971698760986,-5.475971698760986,-5.475971698760986,-5.475971698760986,-5.475971698760986,-5.475971698760986,-5.475971221923828,-5.475971221923828,-5.475971221923828,-5.475971221923828,-5.475971221923828,-5.475970268249512,-5.475970268249512,-5.4759697914123535,-5.4759697914123535,-5.475969314575195,-5.475969314575195,-5.475968837738037,-5.475967884063721,-5.4759674072265625,-5.4759674072265625,-5.475966930389404,-5.475966453552246,-5.475965976715088,-5.47596549987793,-5.4759650230407715,-5.475964069366455,-5.475963592529297,-5.475963115692139,-5.475963115692139,-5.475962162017822,-5.475961685180664,-5.475961208343506,-5.475960731506348,-5.4759602546691895,-5.475959777832031,-5.475959300994873,-5.475958824157715,-5.475957870483398,-5.47595739364624,-5.475956916809082,-5.475956439971924,-5.475955486297607,-5.475955486297607,-5.475955009460449,-5.475954055786133,-5.475954055786133,-5.475953578948975,-5.475952625274658,-5.475951671600342,-5.475951671600342,-5.475951194763184,-5.475950717926025,-5.475950241088867,-5.475949764251709,-5.475949287414551,-5.475948810577393,-5.475947856903076,-5.475947380065918,-5.475947380065918,-5.475946426391602,-5.475945949554443,-5.475945472717285,-5.475944995880127,-5.475944519042969,-5.4759440422058105,-5.475943565368652,-5.475943088531494,-5.475942611694336,-5.475942134857178,-5.475941181182861,-5.475940227508545,-5.475940227508545,-5.475939750671387,-5.47593879699707,-5.475938320159912,-5.475938320159912,-5.475937366485596,-5.475936412811279,-5.475935935974121,-5.475935935974121,-5.475935935974121,-5.475934982299805,-5.4759345054626465,-5.475934028625488,-5.47593355178833,-5.475932598114014,-5.475932598114014,-5.4759321212768555,-5.475931644439697,-5.475931167602539,-5.475930690765381,-5.475930690765381,-5.4759297370910645,-5.4759297370910645,-5.475928783416748,-5.475928783416748,-5.47592830657959,-5.47592830657959,-5.475927352905273,-5.475927352905273,-5.475926876068115,-5.475926399230957,-5.475926399230957,-5.475925922393799,-5.475925445556641,-5.475925445556641,-5.475924968719482,-5.475924968719482,-5.475924491882324,-5.475924491882324,-5.475924491882324,-5.475924491882324,-5.475924015045166,-5.475924015045166,-5.475924015045166,-5.475924015045166,-5.475924015045166,-5.475923538208008,-5.475923538208008,-5.475923538208008,-5.475923538208008,-5.475923538208008,-5.475923538208008,-5.475923538208008,-5.475923538208008,-5.475924015045166,-5.475924015045166,-5.475924015045166,-5.475924015045166,-5.475924491882324,-5.475924491882324,-5.475924491882324,-5.475924491882324,-5.475925445556641,-5.475925445556641,-5.475925922393799,-5.475925922393799,-5.475925922393799,-5.475926399230957,-5.475926399230957,-5.475926876068115,-5.475927352905273,-5.475927829742432,-5.47592830657959,-5.475928783416748,-5.475928783416748,-5.475929260253906,-5.4759297370910645,-5.475930213928223,-5.475930690765381,-5.475930690765381,-5.475931167602539,-5.475931644439697,-5.4759321212768555,-5.475932598114014,-5.475932598114014,-5.475933074951172,-5.47593355178833,-5.475934028625488,-5.4759345054626465,-5.4759345054626465,-5.475934982299805,-5.475935459136963,-5.475935935974121,-5.475936412811279,-5.475936412811279,-5.4759368896484375,-5.475937366485596,-5.475937843322754,-5.475938320159912,-5.475938320159912,-5.47593879699707,-5.47593879699707,-5.4759392738342285,-5.475939750671387,-5.475940227508545,-5.475940227508545,-5.475940704345703,-5.475940704345703,-5.475941181182861,-5.475941181182861,-5.475941181182861,-5.475942134857178,-5.475942134857178,-5.475942134857178,-5.475942134857178,-5.475942134857178,-5.475942134857178,-5.475942611694336,-5.475942611694336,-5.475942611694336,-5.475943088531494,-5.475943088531494,-5.4759440422058105,-5.4759440422058105,-5.4759440422058105,-5.4759440422058105,-5.4759440422058105,-5.4759440422058105,-5.4759440422058105,-5.4759440422058105,-5.4759440422058105,-5.475944519042969,-5.475944995880127,-5.475944995880127,-5.475944995880127,-5.475944995880127,-5.475944995880127,-5.475944995880127],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"#AB63FA","size":3},"mode":"markers","name":"cluster 3","x":[-20.593891143798828,-20.59389305114746,-20.59389305114746,-20.59389305114746,-20.59389305114746,-20.593894958496094,-20.593894958496094,-20.593894958496094,-20.593896865844727,-20.593896865844727,-20.59389877319336,-20.59389877319336,-20.593900680541992,-20.593900680541992,-20.593900680541992,-20.593902587890625,-20.593902587890625,-20.593904495239258,-20.59390640258789,-20.593908309936523,-20.593908309936523,-20.593910217285156,-20.59391212463379,-20.59391212463379,-20.593914031982422,-20.593914031982422,-20.593915939331055,-20.593917846679688,-20.593917846679688,-20.593921661376953,-20.593923568725586,-20.593923568725586,-20.59392547607422,-20.59392547607422,-20.59392547607422,-20.593929290771484,-20.593929290771484,-20.593931198120117,-20.593935012817383,-20.593935012817383,-20.59393882751465,-20.59393882751465,-20.59393882751465,-20.59394073486328,-20.59394073486328,-20.593944549560547,-20.593944549560547,-20.59394645690918,-20.59394645690918,-20.593950271606445,-20.593950271606445,-20.59395408630371,-20.59395408630371,-20.593955993652344,-20.593955993652344,-20.593957901000977,-20.59395980834961,-20.593961715698242,-20.593961715698242,-20.593961715698242,-20.593963623046875,-20.593965530395508,-20.59396743774414,-20.593969345092773,-20.593969345092773,-20.593971252441406,-20.59397315979004,-20.59397315979004,-20.593975067138672,-20.593975067138672,-20.593975067138672,-20.593976974487305,-20.593976974487305,-20.593976974487305,-20.593978881835938,-20.59398078918457,-20.593982696533203,-20.593982696533203,-20.593984603881836,-20.593984603881836,-20.593984603881836,-20.59398651123047,-20.59398651123047,-20.59398651123047,-20.59398651123047,-20.59398651123047,-20.59398651123047,-20.5939884185791,-20.5939884185791,-20.593990325927734,-20.593990325927734,-20.593990325927734,-20.593990325927734,-20.593990325927734,-20.593992233276367,-20.593992233276367,-20.593994140625,-20.593994140625,-20.593994140625,-20.593994140625,-20.593994140625,-20.593994140625,-20.593994140625,-20.593994140625,-20.593994140625,-20.593994140625,-20.593994140625,-20.593992233276367,-20.593992233276367,-20.593992233276367,-20.593990325927734,-20.593990325927734,-20.593990325927734,-20.593990325927734,-20.593990325927734,-20.593990325927734,-20.5939884185791,-20.59398651123047,-20.59398651123047,-20.59398651123047,-20.59398651123047,-20.59398651123047,-20.59398651123047,-20.59398651123047,-20.59398651123047,-20.593984603881836,-20.593982696533203,-20.593982696533203,-20.593982696533203,-20.59398078918457,-20.59398078918457,-20.59398078918457,-20.593978881835938,-20.593978881835938,-20.593976974487305,-20.593976974487305,-20.593976974487305,-20.593975067138672,-20.593975067138672,-20.593975067138672,-20.593975067138672,-20.593975067138672,-20.593975067138672,-20.593971252441406,-20.593971252441406,-20.593971252441406,-20.593969345092773,-20.593969345092773,-20.593969345092773,-20.593969345092773,-20.593969345092773,-20.593965530395508,-20.593965530395508,-20.593965530395508,-20.593963623046875,-20.593963623046875,-20.593961715698242,-20.593961715698242,-20.593961715698242,-20.593961715698242,-20.593961715698242,-20.59395980834961,-20.593957901000977,-20.593957901000977,-20.593957901000977,-20.593957901000977,-20.593957901000977,-20.593955993652344,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.593952178955078,-20.593952178955078,-20.593952178955078,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593948364257812,-20.593948364257812,-20.593948364257812,-20.593948364257812,-20.593948364257812,-20.59394645690918,-20.59394645690918,-20.59394645690918,-20.59394645690918,-20.59394645690918,-20.59394645690918,-20.59394645690918,-20.59394645690918,-20.59394645690918,-20.59394645690918,-20.59394645690918,-20.59394645690918,-20.593948364257812,-20.593948364257812,-20.593948364257812,-20.593948364257812,-20.593948364257812,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593952178955078,-20.593952178955078,-20.593952178955078,-20.593952178955078,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.593955993652344,-20.593955993652344,-20.593955993652344,-20.593955993652344,-20.593955993652344,-20.593955993652344,-20.593955993652344,-20.593955993652344,-20.593955993652344,-20.593957901000977,-20.593957901000977],"y":[9.09961223602295,9.099610328674316,9.099608421325684,9.099607467651367,9.099604606628418,9.099602699279785,9.099600791931152,9.099599838256836,9.099597930908203,9.099595069885254,9.099593162536621,9.099592208862305,9.099590301513672,9.099589347839355,9.099587440490723,9.09958553314209,9.099584579467773,9.09958267211914,9.099581718444824,9.099579811096191,9.099577903747559,9.099577903747559,9.099576950073242,9.09957504272461,9.099573135375977,9.09957218170166,9.099571228027344,9.099570274353027,9.099569320678711,9.099568367004395,9.099567413330078,9.099567413330078,9.099565505981445,9.099565505981445,9.099565505981445,9.099564552307129,9.099564552307129,9.099563598632812,9.099563598632812,9.099562644958496,9.099562644958496,9.099562644958496,9.099562644958496,9.099562644958496,9.099562644958496,9.099562644958496,9.099562644958496,9.099562644958496,9.099562644958496,9.099562644958496,9.099562644958496,9.099563598632812,9.099563598632812,9.099564552307129,9.099564552307129,9.099564552307129,9.099565505981445,9.099565505981445,9.099565505981445,9.099566459655762,9.099566459655762,9.099567413330078,9.099568367004395,9.099569320678711,9.099569320678711,9.099570274353027,9.099571228027344,9.09957218170166,9.09957218170166,9.099573135375977,9.099573135375977,9.099574089050293,9.09957504272461,9.099575996398926,9.099576950073242,9.099576950073242,9.099577903747559,9.099577903747559,9.099579811096191,9.099579811096191,9.099581718444824,9.099581718444824,9.09958267211914,9.099584579467773,9.09958553314209,9.09958553314209,9.099586486816406,9.099587440490723,9.099588394165039,9.099589347839355,9.099589347839355,9.099590301513672,9.099591255187988,9.099592208862305,9.099593162536621,9.099593162536621,9.099594116210938,9.099595069885254,9.099595069885254,9.099595069885254,9.099596977233887,9.099596977233887,9.099597930908203,9.099597930908203,9.099597930908203,9.099599838256836,9.099599838256836,9.099600791931152,9.099600791931152,9.099601745605469,9.099602699279785,9.099602699279785,9.099603652954102,9.099604606628418,9.099604606628418,9.099605560302734,9.099605560302734,9.09960651397705,9.09960651397705,9.09960651397705,9.099607467651367,9.099608421325684,9.099608421325684,9.099608421325684,9.099609375,9.099610328674316,9.099610328674316,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.099613189697266,9.099613189697266,9.099615097045898,9.099615097045898,9.099615097045898,9.099615097045898,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099615097045898,9.099615097045898,9.099615097045898,9.099615097045898,9.099615097045898,9.099615097045898,9.099615097045898,9.099615097045898,9.099613189697266,9.099613189697266,9.099613189697266,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.099610328674316,9.099610328674316,9.099610328674316,9.099609375,9.099608421325684,9.099608421325684,9.099608421325684,9.099608421325684,9.099607467651367,9.099607467651367,9.099607467651367,9.09960651397705,9.09960651397705,9.09960651397705,9.099605560302734,9.099605560302734,9.099605560302734,9.099604606628418,9.099604606628418,9.099604606628418,9.099604606628418,9.099604606628418,9.099603652954102,9.099603652954102,9.099602699279785,9.099602699279785,9.099602699279785,9.099602699279785,9.099602699279785,9.099600791931152,9.099600791931152,9.099600791931152,9.099600791931152,9.099600791931152,9.099599838256836,9.099599838256836,9.099599838256836,9.099599838256836,9.099599838256836,9.099599838256836,9.099597930908203,9.099597930908203,9.099597930908203,9.099597930908203,9.099597930908203,9.099597930908203,9.099597930908203,9.099597930908203,9.099596977233887,9.099596977233887,9.099596977233887,9.099596977233887,9.099596977233887,9.099596977233887,9.099596977233887,9.099596977233887,9.099596977233887,9.099596977233887,9.099596977233887],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"#FFA15A","size":3},"mode":"markers","name":"cluster 4","x":[-9.634350776672363,-9.63435173034668,-9.63435173034668,-9.634353637695312,-9.634354591369629,-9.634354591369629,-9.634355545043945,-9.634355545043945,-9.634356498718262,-9.634358406066895,-9.634358406066895,-9.634359359741211,-9.634360313415527,-9.634361267089844,-9.63436222076416,-9.63436222076416,-9.634363174438477,-9.63436508178711,-9.63436508178711,-9.634366035461426,-9.634366989135742,-9.634368896484375,-9.634369850158691,-9.634369850158691,-9.634370803833008,-9.634371757507324,-9.63437271118164,-9.634373664855957,-9.634374618530273,-9.63437557220459,-9.634376525878906,-9.634377479553223,-9.634377479553223,-9.634378433227539,-9.634379386901855,-9.634380340576172,-9.634381294250488,-9.634381294250488,-9.634382247924805,-9.634383201599121,-9.634384155273438,-9.634385108947754,-9.634385108947754,-9.63438606262207,-9.634387016296387,-9.634387969970703,-9.63438892364502,-9.63438892364502,-9.634389877319336,-9.634390830993652,-9.634391784667969,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634393692016602,-9.634394645690918,-9.634395599365234,-9.63439655303955,-9.63439655303955,-9.634397506713867,-9.634398460388184,-9.634398460388184,-9.634398460388184,-9.634400367736816,-9.634400367736816,-9.634401321411133,-9.634401321411133,-9.634403228759766,-9.634403228759766,-9.634403228759766,-9.634404182434082,-9.634404182434082,-9.634405136108398,-9.634405136108398,-9.634405136108398,-9.634406089782715,-9.634406089782715,-9.634407997131348,-9.634407997131348,-9.634407997131348,-9.634407997131348,-9.634408950805664,-9.634408950805664,-9.63440990447998,-9.634410858154297,-9.634410858154297,-9.634410858154297,-9.634410858154297,-9.634411811828613,-9.634411811828613,-9.634411811828613,-9.634411811828613,-9.634411811828613,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.634411811828613,-9.634411811828613,-9.634411811828613,-9.634411811828613,-9.634411811828613,-9.634410858154297,-9.634410858154297,-9.634410858154297,-9.634410858154297,-9.634410858154297,-9.634410858154297,-9.63440990447998,-9.63440990447998,-9.63440990447998,-9.634408950805664,-9.634408950805664,-9.634408950805664,-9.634407997131348,-9.634407997131348,-9.634407997131348,-9.634407997131348,-9.634407997131348,-9.634407997131348,-9.634407043457031,-9.634406089782715,-9.634405136108398,-9.634405136108398,-9.634404182434082,-9.634404182434082,-9.634404182434082,-9.634403228759766,-9.634403228759766,-9.634403228759766,-9.634401321411133,-9.634401321411133,-9.634400367736816,-9.634400367736816,-9.634400367736816,-9.634400367736816,-9.634400367736816,-9.634398460388184,-9.634398460388184,-9.634398460388184,-9.634397506713867,-9.63439655303955,-9.63439655303955,-9.63439655303955,-9.63439655303955,-9.634395599365234,-9.634395599365234,-9.634395599365234,-9.634394645690918,-9.634393692016602,-9.634393692016602,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634391784667969,-9.634390830993652,-9.634390830993652,-9.634390830993652,-9.634390830993652,-9.634390830993652,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.63438606262207,-9.63438606262207,-9.63438606262207,-9.63438606262207,-9.63438606262207,-9.63438606262207,-9.63438606262207,-9.63438606262207,-9.63438606262207,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.634389877319336,-9.634389877319336,-9.634390830993652,-9.634390830993652,-9.634390830993652,-9.634390830993652,-9.634390830993652,-9.634390830993652,-9.634390830993652,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634393692016602,-9.634393692016602,-9.634393692016602,-9.634393692016602],"y":[24.50691032409668,24.50691032409668,24.506906509399414,24.506906509399414,24.50690460205078,24.50690460205078,24.50690460205078,24.50690269470215,24.506900787353516,24.506900787353516,24.506898880004883,24.50689697265625,24.50689697265625,24.50689697265625,24.50689697265625,24.506895065307617,24.506895065307617,24.506893157958984,24.506893157958984,24.506893157958984,24.50689125061035,24.50688934326172,24.50688934326172,24.50688934326172,24.50688934326172,24.506887435913086,24.506887435913086,24.506885528564453,24.506885528564453,24.506885528564453,24.506881713867188,24.506881713867188,24.506881713867188,24.506881713867188,24.506881713867188,24.506879806518555,24.506877899169922,24.50687599182129,24.506874084472656,24.506874084472656,24.506874084472656,24.506874084472656,24.506874084472656,24.50687026977539,24.50687026977539,24.506868362426758,24.506868362426758,24.506866455078125,24.506866455078125,24.506864547729492,24.50686264038086,24.50686264038086,24.506860733032227,24.506860733032227,24.506860733032227,24.506858825683594,24.506858825683594,24.50685691833496,24.50685691833496,24.506855010986328,24.506853103637695,24.506851196289062,24.506851196289062,24.50684928894043,24.50684928894043,24.50684928894043,24.50684928894043,24.506847381591797,24.506845474243164,24.506845474243164,24.50684356689453,24.50684356689453,24.5068416595459,24.506839752197266,24.506839752197266,24.506839752197266,24.506839752197266,24.506837844848633,24.5068359375,24.5068359375,24.506834030151367,24.506834030151367,24.506834030151367,24.506832122802734,24.506832122802734,24.506832122802734,24.5068302154541,24.5068302154541,24.50682830810547,24.506826400756836,24.506826400756836,24.506826400756836,24.506826400756836,24.506826400756836,24.506824493408203,24.506824493408203,24.506824493408203,24.506824493408203,24.506820678710938,24.506820678710938,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506820678710938,24.50682258605957,24.506824493408203,24.506824493408203,24.506824493408203,24.506824493408203,24.506824493408203,24.506826400756836,24.506826400756836,24.506826400756836,24.50682830810547,24.50682830810547,24.506832122802734,24.506832122802734,24.506832122802734,24.506832122802734,24.506834030151367,24.506834030151367,24.5068359375,24.5068359375,24.5068359375,24.506837844848633,24.506837844848633,24.506839752197266,24.5068416595459,24.5068416595459,24.5068416595459,24.50684356689453,24.50684356689453,24.506845474243164,24.506845474243164,24.506845474243164,24.50684928894043,24.50684928894043,24.50684928894043,24.50684928894043,24.50684928894043,24.506851196289062,24.506851196289062,24.506851196289062,24.506853103637695,24.506853103637695,24.506855010986328,24.50685691833496,24.50685691833496,24.50685691833496,24.50685691833496,24.50685691833496,24.506858825683594,24.506858825683594,24.506858825683594,24.506858825683594,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506858825683594,24.506858825683594,24.506858825683594,24.506858825683594,24.506858825683594,24.506858825683594,24.506858825683594,24.50685691833496,24.50685691833496,24.50685691833496,24.50685691833496,24.50685691833496,24.50685691833496,24.50685691833496,24.50685691833496,24.50685691833496,24.506855010986328,24.506855010986328,24.506855010986328,24.506855010986328,24.506855010986328,24.506853103637695,24.506851196289062,24.506851196289062],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"#19D3F3","size":3},"mode":"markers","name":"cluster 5","x":[24.875041961669922,24.87504005432129,24.875038146972656,24.875038146972656,24.875036239624023,24.87503433227539,24.875032424926758,24.875030517578125,24.875030517578125,24.875030517578125,24.875028610229492,24.87502670288086,24.875024795532227,24.875022888183594,24.875022888183594,24.875022888183594,24.87502098083496,24.875019073486328,24.875017166137695,24.875015258789062,24.875015258789062,24.87501335144043,24.87501335144043,24.875009536743164,24.875009536743164,24.87500762939453,24.87500762939453,24.87500762939453,24.8750057220459,24.875003814697266,24.875001907348633,24.875,24.875,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.8749942779541,24.8749942779541,24.8749942779541,24.87499237060547,24.87499237060547,24.874990463256836,24.874990463256836,24.874990463256836,24.874988555908203,24.874988555908203,24.874988555908203,24.874988555908203,24.87498664855957,24.874984741210938,24.874984741210938,24.874984741210938,24.874984741210938,24.874982833862305,24.874982833862305,24.874982833862305,24.874982833862305,24.874982833862305,24.874980926513672,24.874980926513672,24.874980926513672,24.87497901916504,24.87497901916504,24.87497901916504,24.87497901916504,24.874977111816406,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.87497901916504,24.87497901916504,24.87497901916504,24.874980926513672,24.874980926513672,24.874982833862305,24.874982833862305,24.874982833862305,24.874982833862305,24.874982833862305,24.874982833862305,24.874982833862305,24.874984741210938,24.874984741210938,24.874984741210938,24.87498664855957,24.874988555908203,24.874988555908203,24.874988555908203,24.874988555908203,24.874990463256836,24.874990463256836,24.874990463256836,24.87499237060547,24.87499237060547,24.8749942779541,24.8749942779541,24.8749942779541,24.8749942779541,24.874996185302734,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.875,24.875,24.875,24.875,24.875003814697266,24.875003814697266,24.875003814697266,24.8750057220459,24.8750057220459,24.8750057220459,24.8750057220459,24.8750057220459,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.8750057220459,24.8750057220459,24.875003814697266,24.875003814697266,24.875003814697266,24.875003814697266,24.875003814697266,24.875001907348633,24.875001907348633,24.875001907348633,24.875001907348633,24.875001907348633,24.875,24.875,24.875,24.875,24.875,24.875,24.875,24.875,24.875,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874996185302734,24.874996185302734,24.874996185302734,24.874996185302734],"y":[3.7252485752105713,3.725252389907837,3.7252562046051025,3.72525954246521,3.7252631187438965,3.725266456604004,3.7252700328826904,3.7252728939056396,3.725275993347168,3.7252790927886963,3.7252817153930664,3.7252848148345947,3.725287437438965,3.725289821624756,3.725292444229126,3.725295066833496,3.725297451019287,3.725299835205078,3.725301742553711,3.7253036499023438,3.7253055572509766,3.7253074645996094,3.725308895111084,3.7253105640411377,3.7253119945526123,3.725313425064087,3.7253146171569824,3.725316286087036,3.7253172397613525,3.725318431854248,3.7253196239471436,3.725320339202881,3.7253215312957764,3.725322723388672,3.725323438644409,3.7253241539001465,3.7253246307373047,3.725325107574463,3.7253258228302,3.7253265380859375,3.7253265380859375,3.725327253341675,3.725327253341675,3.725327253341675,3.725327730178833,3.725327968597412,3.725327968597412,3.725327968597412,3.725327968597412,3.725327968597412,3.725327730178833,3.725327730178833,3.725327253341675,3.725327253341675,3.725327253341675,3.7253265380859375,3.7253265380859375,3.7253265380859375,3.7253258228302,3.725325107574463,3.725325107574463,3.7253241539001465,3.725323438644409,3.72532320022583,3.7253222465515137,3.7253220081329346,3.725321054458618,3.725320339202881,3.7253196239471436,3.725318431854248,3.7253177165985107,3.7253170013427734,3.725315809249878,3.7253150939941406,3.725313901901245,3.7253127098083496,3.7253119945526123,3.725310802459717,3.7253096103668213,3.725308895111084,3.7253074645996094,3.725306749343872,3.7253057956695557,3.72530460357666,3.7253036499023438,3.7253026962280273,3.725301742553711,3.7253005504608154,3.72529935836792,3.7252981662750244,3.725297451019287,3.7252960205078125,3.725295066833496,3.725294351577759,3.725292921066284,3.725292205810547,3.725290536880493,3.725289821624756,3.7252886295318604,3.725287914276123,3.7252867221832275,3.7252860069274902,3.7252848148345947,3.725283622741699,3.725282907485962,3.7252817153930664,3.725280523300171,3.7252798080444336,3.7252790927886963,3.725278377532959,3.7252771854400635,3.725275993347168,3.7252752780914307,3.725274085998535,3.7252728939056396,3.7252721786499023,3.725271463394165,3.7252707481384277,3.7252700328826904,3.725269079208374,3.7252676486968994,3.725266933441162,3.7252659797668457,3.7252652645111084,3.725264549255371,3.725263833999634,3.7252631187438965,3.72526216506958,3.7252614498138428,3.7252607345581055,3.725260019302368,3.725259304046631,3.7252583503723145,3.7252581119537354,3.725257396697998,3.72525691986084,3.7252562046051025,3.7252554893493652,3.725254535675049,3.7252542972564697,3.7252538204193115,3.725253105163574,3.725252628326416,3.725252389907837,3.7252516746520996,3.7252516746520996,3.725250720977783,3.725250720977783,3.725250005722046,3.725250005722046,3.7252495288848877,3.7252492904663086,3.7252488136291504,3.7252485752105713,3.725248098373413,3.725248098373413,3.725247621536255,3.725247621536255,3.725247621536255,3.725247621536255,3.7252469062805176,3.7252469062805176,3.7252469062805176,3.7252469062805176,3.7252469062805176,3.7252469062805176,3.7252469062805176,3.7252469062805176,3.725247383117676,3.725247621536255,3.725247621536255,3.725247621536255,3.725248098373413,3.725248098373413,3.7252485752105713,3.7252485752105713,3.7252485752105713,3.7252492904663086,3.7252492904663086,3.7252492904663086,3.7252495288848877,3.725250005722046,3.725250482559204,3.725250720977783,3.7252511978149414,3.7252516746520996,3.7252519130706787,3.725252389907837,3.725253105163574,3.7252535820007324,3.7252538204193115,3.725254535675049,3.725254535675049,3.7252554893493652,3.7252554893493652,3.7252562046051025,3.72525691986084,3.725257635116577,3.7252581119537354,3.7252583503723145,3.725259304046631,3.72525954246521,3.725260019302368,3.7252607345581055,3.7252612113952637,3.7252614498138428,3.72526216506958,3.7252631187438965,3.7252633571624756,3.725263833999634,3.725264549255371,3.7252652645111084,3.7252657413482666,3.7252659797668457,3.725266933441162,3.7252676486968994,3.7252678871154785,3.7252683639526367,3.725269079208374,3.7252700328826904,3.7252700328826904,3.7252707481384277,3.7252707481384277,3.725271463394165,3.7252721786499023,3.7252726554870605,3.7252728939056396,3.725273847579956,3.725273847579956,3.7252745628356934,3.7252748012542725,3.7252752780914307,3.725275993347168,3.725276470184326,3.7252767086029053,3.7252771854400635,3.7252771854400635,3.7252776622772217,3.725277900695801,3.725278377532959,3.725278615951538,3.7252790927886963,3.7252790927886963,3.7252795696258545,3.7252798080444336,3.7252798080444336,3.7252798080444336,3.725280284881592,3.725280523300171,3.725280523300171],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"}],                        {"template":{"data":{"scatter":[{"marker":{"color":"#d92310"},"type":"scatter"}]},"layout":{"height":576,"paper_bgcolor":"#fcfcfc","plot_bgcolor":"#fcfcfc","width":1024}},"xaxis":{"zeroline":false},"yaxis":{"zeroline":false}},                        {"responsive": true}                    ).then(function(){
                            
var gd = document.getElementById('549d3d93-edec-4655-a542-29441f8df229');
var x = new MutationObserver(function (mutations, observer) {{
        var display = window.getComputedStyle(gd).display;
        if (!display || display === 'none') {{
            console.log([gd, 'removed!']);
            Plotly.purge(gd);
            observer.disconnect();
        }}
}});

// Listen for the removal of the full notebook cells
var notebookContainer = gd.closest('#notebook-container');
if (notebookContainer) {{
    x.observe(notebookContainer, {childList: true});
}}

// Listen for the clearing of the current output cell
var outputEl = gd.closest('.output');
if (outputEl) {{
    x.observe(outputEl, {childList: true});
}}

                        })                };                });            </script>        </div>
</div>
</div>
<p>All points have converged.</p>
<div id="f478d48c" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb25" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb25-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>timeit <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>n <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span> meanshift(data)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>1.7 s ± 282 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)</code></pre>
</div>
</div>
<p>The algorithm took roughly 1.5 seconds to run 5 iterations. We’ll optimize the algorithm further in Optimized Implementation.</p>
<p>As we can see below, simply moving the algorithm to the GPU won’t help —&nbsp;in fact, it becamse a bit slower.</p>
<div id="051dccc0" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb27" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb27-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> update(X):</span>
<span id="cb27-2">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, x <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(X):</span>
<span id="cb27-3">      dist <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> X).square().<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).sqrt()</span>
<span id="cb27-4">      ws <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> gauss_kernel(x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>dist, mean<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, std<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>bw)</span>
<span id="cb27-5">      X[i] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (ws[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> X).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> ws.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>()</span>
<span id="cb27-6"></span>
<span id="cb27-7"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> meanshift(data):</span>
<span id="cb27-8">   X <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> data.clone().to(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'cuda'</span>)</span>
<span id="cb27-9">   <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>): update(X)</span>
<span id="cb27-10">   <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> X.detach().cpu()</span>
<span id="cb27-11"></span>
<span id="cb27-12"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>timeit <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>n <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span> meanshift(data)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>1.67 s ± 49.7 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)</code></pre>
</div>
</div>
</section>
<section id="animation" class="level3 page-columns page-full">
<h3 class="anchored" data-anchor-id="animation">Animation</h3>
<p>Let’s see meanshift clustering happen in real time.</p>
<div id="c2caf2fb" class="cell page-columns page-full">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb29" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb29-1">X <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> data.clone()</span>
<span id="cb29-2">fig <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> plot_data(centroids<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, X, n_samples, display<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>)</span>
<span id="cb29-3">fig.update_layout(xaxis_range<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span>], yaxis_range<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span>],  updatemenus<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'buttons'</span>, buttons<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[</span>
<span id="cb29-4">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>(label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Play'</span>, method<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'animate'</span>, args<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>]),</span>
<span id="cb29-5">    <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>(label<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'Pause'</span>, method<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'animate'</span>, args<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>[[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>], <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">dict</span>(frame_duration<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, frame_redraw<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'False'</span>, mode<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'immediate'</span>, transition_duration<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)])</span>
<span id="cb29-6">])])</span>
<span id="cb29-7"></span>
<span id="cb29-8">frames <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [go.Frame(data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>fig.data)]</span>
<span id="cb29-9"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>):</span>
<span id="cb29-10">    update(X)</span>
<span id="cb29-11">    frames.append(go.Frame(data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>plot_data(centroids<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, X, n_samples, display<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">False</span>).data))</span>
<span id="cb29-12">fig.frames <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> frames</span>
<span id="cb29-13">fig.show()</span></code></pre></div></div>
<div class="cell-output cell-output-display column-page">
<div>                            <div id="7d1b0ec9-5d91-4ba4-b13c-dfc5cff3fd45" class="plotly-graph-div" style="height:576px; width:1024px;"></div>            <script type="text/javascript">                require(["plotly"], function(Plotly) {                    window.PLOTLYENV=window.PLOTLYENV || {};                                    if (document.getElementById("7d1b0ec9-5d91-4ba4-b13c-dfc5cff3fd45")) {                    Plotly.newPlot(                        "7d1b0ec9-5d91-4ba4-b13c-dfc5cff3fd45",                        [{"marker":{"color":"#636EFA","size":3},"mode":"markers","name":"cluster 0","x":[0.6106996536254883,4.454596519470215,2.0711617469787598,1.0110520124435425,4.5163893699646,-0.1486372947692871,4.0289177894592285,2.95975923538208,-1.0943694114685059,6.752066612243652,2.888312816619873,4.768091678619385,1.9764769077301025,-1.6155166625976562,-2.1650285720825195,-0.5145149230957031,2.2578015327453613,2.834491491317749,4.584721565246582,0.5921010971069336,-0.688715934753418,6.113814353942871,1.8596506118774414,3.565117835998535,2.0461254119873047,2.412180185317993,-4.187981128692627,1.7536394596099854,6.076658248901367,1.4662054777145386,5.0048909187316895,1.650177240371704,2.742509603500366,1.2938233613967896,-0.3352804183959961,1.1423156261444092,0.4638735055923462,3.4898533821105957,0.6288788318634033,0.12580561637878418,-2.603978157043457,3.7240519523620605,2.163062572479248,6.361776828765869,1.5535951852798462,4.1370134353637695,0.5990724563598633,3.5654516220092773,1.2442047595977783,4.808256149291992,2.729548692703247,1.533890962600708,3.3024158477783203,-0.2711365222930908,3.5784335136413574,3.4738755226135254,-0.07032990455627441,3.8442697525024414,1.1343374252319336,3.8752074241638184,0.6200094223022461,-0.2625694274902344,1.4806886911392212,3.077441453933716,3.7166671752929688,3.6967945098876953,1.9437216520309448,-2.3270368576049805,5.694780349731445,1.703410267829895,2.728020668029785,0.40372776985168457,3.029271125793457,5.021300315856934,7.112307548522949,4.243080139160156,2.595820188522339,1.5233139991760254,4.06235933303833,1.2589422464370728,3.9698963165283203,2.267824172973633,5.580748081207275,2.814542293548584,0.9386806488037109,0.8993861675262451,0.7550551891326904,4.578845024108887,1.3930007219314575,4.2748003005981445,4.01229190826416,3.0979256629943848,3.13167405128479,5.873199939727783,-2.3652734756469727,0.23277902603149414,1.6450698375701904,-0.16131353378295898,5.316432952880859,-0.746211051940918,-3.4459590911865234,4.096480369567871,4.127533912658691,2.5963215827941895,3.8091964721679688,0.47520267963409424,0.9366261959075928,3.342190980911255,-0.08721661567687988,1.2673484086990356,1.8158373832702637,5.756171226501465,3.4982364177703857,5.422142028808594,2.4125044345855713,3.337184429168701,-0.4337937831878662,2.2619690895080566,1.5083262920379639,1.9040424823760986,0.841778039932251,1.4697105884552002,1.0406396389007568,4.13149881362915,3.8440966606140137,1.5222117900848389,4.206725120544434,2.65280818939209,2.458773612976074,1.0481992959976196,4.258362770080566,4.151905059814453,-0.7333433628082275,1.8043519258499146,2.809670925140381,4.118513107299805,2.112030267715454,2.8926684856414795,3.7863731384277344,6.078733444213867,0.17786622047424316,3.2297608852386475,3.361069679260254,4.22938871383667,1.4906213283538818,2.156731367111206,3.407961368560791,1.0653377771377563,6.439641952514648,4.910748481750488,2.0400807857513428,5.018989086151123,3.889838695526123,3.167424201965332,4.468905448913574,4.915773391723633,3.9555795192718506,0.5957375764846802,3.816124439239502,-0.9412333965301514,-1.058197259902954,2.3830742835998535,3.87819766998291,0.6730018854141235,2.681736469268799,-0.7682609558105469,3.026716709136963,3.8628134727478027,3.148106813430786,3.167198657989502,5.090166091918945,2.068650245666504,3.3243465423583984,-0.19996142387390137,7.687468528747559,7.051206588745117,4.482922554016113,2.7472009658813477,1.6230460405349731,4.623526573181152,1.8923182487487793,2.9435620307922363,0.1830892562866211,2.60666561126709,3.119462251663208,6.189139366149902,-0.413712739944458,-1.0135910511016846,4.135379314422607,2.2551188468933105,5.880044937133789,0.2985837459564209,3.565070152282715,4.694297790527344,-0.8904917240142822,-0.025649309158325195,5.0980730056762695,1.2597852945327759,3.941540241241455,2.772353172302246,-0.18204474449157715,-0.41129565238952637,4.791975975036621,2.0827300548553467,2.2586898803710938,-0.25301527976989746,4.837216377258301,4.088098049163818,2.238393783569336,5.4800310134887695,3.3855934143066406,4.921282768249512,1.7489819526672363,1.8883492946624756,3.6563923358917236,4.024860382080078,2.62627911567688,7.209653377532959,-1.1760749816894531,1.2553073167800903,-0.571690559387207,4.939748287200928,0.19209623336791992,2.2359273433685303,1.525259017944336,3.8941426277160645,4.756255149841309,6.353114128112793,3.989452600479126,3.8916399478912354,6.344674110412598,1.3829160928726196,3.179715156555176,1.0047781467437744,6.336634635925293,3.4817066192626953,2.845355749130249,3.630941867828369,2.1003105640411377,5.563776016235352,-1.263171911239624,-1.5524673461914062,3.9684884548187256,5.099576473236084,3.5895919799804688,6.828782081604004,2.7350287437438965,0.5344339609146118,-0.6981027126312256,-0.6902151107788086],"y":[-20.19911766052246,-24.188343048095703,-20.4461612701416,-23.082050323486328,-22.281217575073242,-22.11271858215332,-18.81918716430664,-18.646093368530273,-21.80953025817871,-21.821704864501953,-19.33500862121582,-22.703832626342773,-21.56529426574707,-21.85576057434082,-19.576440811157227,-24.124313354492188,-21.136274337768555,-15.944525718688965,-22.563756942749023,-22.43811798095703,-18.182846069335938,-23.44659423828125,-21.643089294433594,-20.502317428588867,-21.664033889770508,-21.942182540893555,-23.455249786376953,-18.994644165039062,-21.080272674560547,-25.798601150512695,-21.938365936279297,-19.397350311279297,-20.67559242248535,-19.29376220703125,-24.924785614013672,-22.459728240966797,-18.407161712646484,-21.405635833740234,-21.948190689086914,-19.759958267211914,-20.179737091064453,-20.395484924316406,-23.22544288635254,-18.893400192260742,-21.470991134643555,-18.878507614135742,-20.718656539916992,-17.90732765197754,-19.23033905029297,-23.55394744873047,-21.126134872436523,-19.894866943359375,-16.80714225769043,-17.12339210510254,-21.43614959716797,-23.66242790222168,-21.786884307861328,-20.880727767944336,-22.178525924682617,-19.721088409423828,-18.49786949157715,-19.949764251708984,-19.712493896484375,-18.433025360107422,-20.785696029663086,-22.727603912353516,-22.862499237060547,-22.75919532775879,-24.530500411987305,-19.852903366088867,-24.47193717956543,-18.240379333496094,-21.417892456054688,-23.61248779296875,-22.270471572875977,-20.918540954589844,-22.311174392700195,-20.963150024414062,-23.506885528564453,-20.787317276000977,-23.379852294921875,-20.762178421020508,-22.015539169311523,-22.684114456176758,-22.676895141601562,-20.566917419433594,-21.35162353515625,-20.75017547607422,-22.98044776916504,-20.622966766357422,-22.628801345825195,-17.8162784576416,-19.385879516601562,-22.8177433013916,-23.94515609741211,-21.093578338623047,-20.66701889038086,-19.105106353759766,-22.95493507385254,-21.683509826660156,-21.13545036315918,-19.6022891998291,-19.796276092529297,-21.302955627441406,-23.10927391052246,-23.008304595947266,-27.83803367614746,-23.454715728759766,-25.18522071838379,-18.517133712768555,-22.626859664916992,-21.190433502197266,-19.635047912597656,-21.74361228942871,-22.370267868041992,-22.201234817504883,-21.50897789001465,-22.98897933959961,-20.32002067565918,-18.2002010345459,-19.156137466430664,-22.16558265686035,-16.592864990234375,-20.9410343170166,-21.66925048828125,-20.866079330444336,-22.89394187927246,-21.75556182861328,-24.45231819152832,-20.070878982543945,-14.87507152557373,-21.484704971313477,-23.4167423248291,-19.331729888916016,-22.969881057739258,-20.811262130737305,-17.795503616333008,-22.634695053100586,-22.771560668945312,-17.060901641845703,-23.224815368652344,-21.064428329467773,-21.073396682739258,-20.616165161132812,-19.296003341674805,-20.195350646972656,-23.40139389038086,-17.80548858642578,-21.35091209411621,-22.97028923034668,-21.86427116394043,-24.580934524536133,-22.574420928955078,-20.109445571899414,-20.246047973632812,-20.880678176879883,-22.15427589416504,-21.21795082092285,-21.609981536865234,-20.70313835144043,-20.49033546447754,-21.064477920532227,-19.699352264404297,-22.72942543029785,-19.058795928955078,-21.85211944580078,-20.760223388671875,-23.04998779296875,-23.362812042236328,-21.12179946899414,-17.609493255615234,-22.682052612304688,-22.00928497314453,-22.203414916992188,-23.86651611328125,-20.10556411743164,-24.718358993530273,-22.499277114868164,-24.465852737426758,-19.876663208007812,-21.51488494873047,-21.108518600463867,-18.40947914123535,-25.001358032226562,-19.844623565673828,-19.15580940246582,-21.532291412353516,-21.060213088989258,-21.3889217376709,-23.526735305786133,-18.872238159179688,-23.274763107299805,-21.09376335144043,-24.94708824157715,-22.410192489624023,-20.583330154418945,-17.562864303588867,-20.466636657714844,-17.395614624023438,-21.90605926513672,-20.758373260498047,-20.82671546936035,-13.170121192932129,-18.344348907470703,-24.698637008666992,-20.82878875732422,-24.995908737182617,-19.98826026916504,-20.985315322875977,-18.28809356689453,-18.92946434020996,-19.452714920043945,-20.269887924194336,-21.670387268066406,-21.58736801147461,-18.11713981628418,-22.169952392578125,-20.195409774780273,-19.091581344604492,-19.074148178100586,-18.046857833862305,-18.59525489807129,-21.3765926361084,-19.681989669799805,-24.445711135864258,-18.704004287719727,-17.731538772583008,-25.31211280822754,-22.73049545288086,-21.1287784576416,-21.608978271484375,-24.527162551879883,-22.626277923583984,-21.416810989379883,-23.346149444580078,-21.770475387573242,-23.14167594909668,-24.321273803710938,-24.238615036010742,-20.205543518066406,-18.339942932128906,-20.704547882080078,-20.283615112304688,-19.168262481689453,-19.91609001159668,-20.267263412475586,-20.524757385253906,-20.10521697998047,-17.82305145263672,-24.993026733398438],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"#EF553B","size":3},"mode":"markers","name":"cluster 1","x":[9.87704086303711,9.4225435256958,12.610001564025879,8.097820281982422,11.419466972351074,10.570701599121094,10.606629371643066,10.462532043457031,11.331299781799316,11.382926940917969,11.107633590698242,14.95037841796875,13.36851692199707,15.071146011352539,8.195347785949707,8.854641914367676,11.516806602478027,15.112360000610352,9.312355995178223,12.523109436035156,14.841484069824219,15.487283706665039,10.850504875183105,12.387774467468262,11.285183906555176,11.804227828979492,10.544031143188477,13.17994499206543,14.77381420135498,11.45132827758789,9.2578706741333,13.98930835723877,11.58730697631836,9.93220329284668,12.861495971679688,10.736139297485352,9.71112060546875,12.424819946289062,13.16836929321289,11.584234237670898,5.022521495819092,11.749085426330566,11.312202453613281,10.611576080322266,13.377660751342773,9.172962188720703,12.465993881225586,9.5494384765625,18.93263816833496,9.865697860717773,7.6244330406188965,11.1902437210083,13.258797645568848,9.840498924255371,11.613204002380371,11.311509132385254,10.185104370117188,11.270140647888184,12.95288372039795,12.62736701965332,14.55495834350586,11.71548843383789,9.575156211853027,12.831417083740234,7.172362327575684,10.812312126159668,10.21819019317627,11.4874267578125,10.869904518127441,13.847227096557617,11.776945114135742,10.921489715576172,10.18920612335205,10.632547378540039,11.031829833984375,10.981271743774414,14.026257514953613,9.647284507751465,18.137493133544922,11.064699172973633,10.404289245605469,8.46476936340332,14.196146011352539,10.85347843170166,13.36893081665039,8.35534381866455,14.9078950881958,8.62026309967041,6.610985279083252,11.460588455200195,12.1513090133667,13.989845275878906,7.602276802062988,15.068745613098145,15.283571243286133,10.42579460144043,11.41176700592041,10.820887565612793,11.916272163391113,15.157073974609375,10.195613861083984,14.575783729553223,12.577715873718262,8.752012252807617,8.57979679107666,9.327132225036621,11.21414852142334,10.981815338134766,14.445018768310547,6.476677894592285,11.187596321105957,14.057319641113281,11.362394332885742,8.155521392822266,12.265863418579102,11.399274826049805,9.247962951660156,8.10108757019043,12.582670211791992,10.203760147094727,7.150644302368164,11.416135787963867,8.282318115234375,10.93171215057373,9.920757293701172,12.59582233428955,5.954134464263916,11.401212692260742,11.130741119384766,13.161144256591797,8.818209648132324,10.167387008666992,12.14991569519043,11.352355003356934,11.138047218322754,12.394486427307129,12.976234436035156,12.454710006713867,8.250981330871582,15.54655647277832,10.172869682312012,12.827277183532715,8.86609935760498,11.81514835357666,10.636499404907227,9.271520614624023,9.799882888793945,7.832983016967773,10.821706771850586,10.563729286193848,11.64404582977295,12.557385444641113,15.20111083984375,11.216188430786133,12.359991073608398,10.731277465820312,11.025440216064453,13.450078964233398,9.63072395324707,6.332091331481934,10.858210563659668,8.945043563842773,12.985211372375488,15.53884220123291,12.219693183898926,9.413066864013672,12.850086212158203,9.990818977355957,9.073244094848633,8.647806167602539,13.088233947753906,10.905885696411133,12.547986030578613,10.302464485168457,9.783677101135254,12.08859920501709,9.099506378173828,11.802888870239258,8.442436218261719,11.132010459899902,7.804447174072266,14.370488166809082,11.384010314941406,12.67867660522461,9.699455261230469,12.52734661102295,9.536325454711914,9.684154510498047,12.043754577636719,10.859668731689453,8.470977783203125,12.089127540588379,7.456197261810303,8.83816146850586,11.415051460266113,10.549241065979004,6.805138111114502,11.196460723876953,12.749780654907227,12.636879920959473,10.95596694946289,12.731612205505371,11.659228324890137,14.560370445251465,11.841026306152344,7.931714057922363,10.726155281066895,5.702099323272705,12.137916564941406,15.443826675415039,7.3869781494140625,10.457058906555176,11.095139503479004,8.380328178405762,11.541655540466309,9.862030982971191,15.231411933898926,12.802127838134766,12.960502624511719,12.770841598510742,10.196751594543457,10.122230529785156,5.181766986846924,8.951225280761719,10.136018753051758,5.531148910522461,8.604415893554688,7.1645731925964355,12.691882133483887,13.559928894042969,5.198024272918701,14.200967788696289,7.897911071777344,8.21728229522705,11.644851684570312,10.320767402648926,10.415617942810059,15.876169204711914,11.981152534484863,4.864884853363037,9.275575637817383,13.136369705200195,10.784153938293457,12.803083419799805,11.134258270263672,9.973132133483887,11.717573165893555,2.9842147827148438,10.181731224060059,10.367219924926758],"y":[10.734405517578125,9.335786819458008,13.441376686096191,12.330901145935059,10.063323020935059,11.657186508178711,7.365444660186768,8.999773025512695,12.038965225219727,14.764404296875,10.82178020477295,13.4752779006958,11.392098426818848,10.135046005249023,11.840617179870605,9.776314735412598,9.990473747253418,12.085968971252441,13.8656587600708,7.980899333953857,8.725305557250977,12.899062156677246,8.720598220825195,14.300816535949707,11.632344245910645,10.884347915649414,9.99297046661377,10.354414939880371,8.777225494384766,8.373196601867676,8.037626266479492,9.00489616394043,8.283859252929688,12.120036125183105,9.729784965515137,10.034659385681152,13.342782020568848,13.832403182983398,11.30892276763916,9.003535270690918,9.722219467163086,13.053757667541504,12.826997756958008,7.017003059387207,10.649638175964355,13.679852485656738,9.408282279968262,12.128579139709473,13.113380432128906,12.83919906616211,12.413917541503906,11.668290138244629,6.153925895690918,11.991576194763184,10.793174743652344,12.52327823638916,12.068902969360352,9.22436237335205,10.30783748626709,5.3423004150390625,10.344483375549316,14.47255802154541,7.237033367156982,12.807012557983398,12.02662467956543,12.13406753540039,12.714216232299805,11.554706573486328,11.308341026306152,7.09832763671875,13.935083389282227,11.023280143737793,11.676339149475098,10.078460693359375,8.887862205505371,8.004937171936035,12.172079086303711,8.344019889831543,10.546194076538086,10.278603553771973,9.850561141967773,6.540694236755371,14.094623565673828,13.03080940246582,12.026119232177734,9.844781875610352,14.854454040527344,9.092710494995117,7.083795547485352,13.150472640991211,8.925386428833008,9.54330825805664,12.065450668334961,13.750585556030273,10.335978507995605,14.149402618408203,10.169922828674316,14.469759941101074,12.803152084350586,10.56090259552002,10.896300315856934,10.610678672790527,10.40132999420166,10.194389343261719,9.682408332824707,8.019926071166992,12.813308715820312,7.141301155090332,8.150213241577148,10.157896995544434,10.739936828613281,8.905439376831055,12.959728240966797,14.031454086303711,13.927950859069824,15.988347053527832,8.539347648620605,11.02241039276123,11.853888511657715,10.494282722473145,11.071870803833008,12.508426666259766,10.966612815856934,11.251618385314941,12.862878799438477,11.168071746826172,11.423723220825195,7.485688209533691,14.271825790405273,13.000264167785645,12.808016777038574,8.910547256469727,4.895911693572998,7.373517036437988,14.97317886352539,11.791913032531738,10.086353302001953,12.438005447387695,12.250608444213867,8.70448112487793,9.40768051147461,8.550436019897461,8.311664581298828,11.452293395996094,9.780439376831055,12.431370735168457,12.913421630859375,8.143282890319824,9.135396957397461,11.134149551391602,6.741981029510498,9.244380950927734,10.749717712402344,14.637189865112305,12.528155326843262,9.443887710571289,14.947844505310059,7.758157730102539,13.048039436340332,10.627683639526367,10.81523609161377,10.374131202697754,9.01569652557373,14.85327434539795,8.898709297180176,11.091988563537598,8.544888496398926,13.079777717590332,12.462029457092285,6.712798595428467,9.902111053466797,10.244808197021484,7.307023048400879,9.82799243927002,9.81595230102539,12.278499603271484,12.8430757522583,14.464896202087402,10.822654724121094,10.515324592590332,11.292708396911621,10.368403434753418,9.722280502319336,11.41006088256836,14.371049880981445,12.479593276977539,11.51334285736084,9.181450843811035,11.381587028503418,11.955004692077637,8.314370155334473,13.114908218383789,14.425192832946777,11.066229820251465,9.404319763183594,14.337783813476562,7.97857666015625,9.011209487915039,15.631593704223633,11.388583183288574,14.366738319396973,11.034764289855957,8.076003074645996,9.505967140197754,12.511550903320312,8.819988250732422,7.850310325622559,19.094078063964844,13.645238876342773,12.414156913757324,10.631463050842285,10.430276870727539,9.743120193481445,10.801138877868652,9.165804862976074,13.029094696044922,10.357752799987793,8.63907241821289,6.381320953369141,9.96885871887207,8.676495552062988,14.108659744262695,10.252354621887207,10.053375244140625,9.217528343200684,11.634859085083008,10.610607147216797,13.862188339233398,14.077072143554688,12.144886016845703,6.061443328857422,9.93949031829834,14.236883163452148,11.515740394592285,9.876175880432129,12.265829086303711,4.3912739753723145,8.761274337768555,10.186405181884766,11.717260360717773,12.657522201538086,6.422496318817139,12.245983123779297,11.363253593444824,9.916359901428223,9.322500228881836,12.07647705078125,10.818828582763672,10.659802436828613,6.526799201965332],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"#00CC96","size":3},"mode":"markers","name":"cluster 2","x":[-23.496248245239258,-19.102161407470703,-20.136016845703125,-16.482664108276367,-16.349597930908203,-19.713245391845703,-18.65350341796875,-13.829034805297852,-18.291528701782227,-19.674604415893555,-18.3510799407959,-17.09149932861328,-17.577880859375,-20.840408325195312,-17.026063919067383,-18.766075134277344,-18.991413116455078,-15.431722640991211,-15.667441368103027,-16.49349594116211,-18.01854705810547,-18.996410369873047,-20.137609481811523,-21.6656551361084,-18.331777572631836,-18.460737228393555,-17.945327758789062,-14.076920509338379,-22.975576400756836,-20.383657455444336,-16.282447814941406,-17.628402709960938,-18.828432083129883,-23.07760238647461,-17.44770622253418,-18.911293029785156,-17.204139709472656,-15.39111614227295,-15.860858917236328,-19.705379486083984,-20.822938919067383,-16.104167938232422,-15.548961639404297,-18.728506088256836,-15.924317359924316,-16.256725311279297,-18.9020938873291,-17.295326232910156,-19.94478988647461,-20.530868530273438,-18.124982833862305,-18.22002410888672,-16.544612884521484,-15.984344482421875,-21.301803588867188,-20.72646713256836,-19.2755126953125,-21.295223236083984,-17.879823684692383,-21.625612258911133,-23.16211700439453,-19.277111053466797,-21.854236602783203,-21.373796463012695,-20.612863540649414,-19.7716007232666,-18.101654052734375,-13.594627380371094,-15.992204666137695,-19.817270278930664,-19.524595260620117,-16.413419723510742,-19.63754653930664,-20.195295333862305,-18.661693572998047,-23.166744232177734,-25.767223358154297,-17.47901725769043,-20.107112884521484,-18.87466049194336,-14.021196365356445,-23.9616641998291,-17.631515502929688,-16.309242248535156,-21.137012481689453,-21.122529983520508,-17.305912017822266,-19.604686737060547,-16.410690307617188,-16.7831974029541,-20.05327606201172,-15.291223526000977,-19.566797256469727,-25.432048797607422,-22.283740997314453,-19.412412643432617,-16.233285903930664,-18.915956497192383,-17.18501853942871,-22.00074005126953,-17.94850730895996,-20.63845443725586,-17.973421096801758,-21.913644790649414,-19.405956268310547,-18.921245574951172,-14.960383415222168,-14.140716552734375,-19.379091262817383,-15.164407730102539,-19.23599624633789,-17.085628509521484,-24.900020599365234,-17.930837631225586,-15.017277717590332,-18.39430046081543,-18.29949951171875,-19.81678009033203,-16.499399185180664,-21.1153621673584,-20.64909553527832,-16.530471801757812,-18.152694702148438,-19.830692291259766,-17.068748474121094,-16.368009567260742,-22.440576553344727,-24.575397491455078,-20.936744689941406,-16.465473175048828,-16.289825439453125,-16.341110229492188,-19.04955291748047,-23.555402755737305,-19.5102481842041,-18.35858917236328,-17.890913009643555,-19.442907333374023,-14.255441665649414,-19.23705291748047,-19.83909034729004,-18.734312057495117,-19.848955154418945,-21.674922943115234,-17.039281845092773,-16.802776336669922,-19.45977210998535,-16.507213592529297,-17.979259490966797,-21.164430618286133,-16.55664825439453,-19.571863174438477,-18.527997970581055,-16.438730239868164,-18.222482681274414,-17.97646713256836,-18.645158767700195,-21.904409408569336,-17.995407104492188,-14.85053539276123,-15.628301620483398,-19.503097534179688,-19.802371978759766,-23.55690574645996,-20.865854263305664,-21.97210121154785,-17.619220733642578,-17.55777931213379,-18.90250015258789,-19.595022201538086,-22.55715560913086,-18.7069149017334,-15.946229934692383,-17.116031646728516,-22.056068420410156,-18.132993698120117,-17.69864273071289,-18.772863388061523,-17.69382095336914,-18.974563598632812,-18.597265243530273,-19.086097717285156,-19.763315200805664,-19.784135818481445,-19.49692153930664,-22.22881317138672,-19.871448516845703,-19.91254425048828,-17.67487335205078,-14.83010482788086,-16.431415557861328,-18.875661849975586,-19.289630889892578,-19.932777404785156,-18.83257293701172,-17.950456619262695,-19.316957473754883,-17.2662410736084,-17.319856643676758,-20.356781005859375,-20.86867904663086,-19.766145706176758,-19.172279357910156,-20.614933013916016,-17.56839942932129,-19.70578384399414,-21.004182815551758,-14.180909156799316,-16.228187561035156,-22.096920013427734,-16.230567932128906,-14.014081954956055,-18.133859634399414,-18.271791458129883,-14.894996643066406,-20.85570526123047,-20.33222770690918,-19.34016990661621,-19.300125122070312,-18.69086265563965,-20.986141204833984,-19.05849266052246,-21.730819702148438,-19.53059959411621,-18.280332565307617,-16.290420532226562,-22.174251556396484,-19.60970687866211,-20.317441940307617,-16.59217643737793,-16.612627029418945,-16.287940979003906,-21.55924415588379,-15.447280883789062,-18.48925018310547,-20.813961029052734,-16.740083694458008,-13.458377838134766,-17.664106369018555,-18.019548416137695,-16.611682891845703,-16.419452667236328,-18.20526885986328,-20.381473541259766,-19.548341751098633,-17.654024124145508,-19.76431655883789,-19.859495162963867,-19.523746490478516,-17.158977508544922],"y":[-2.3969573974609375,-5.214266777038574,-3.7279253005981445,-5.133577823638916,-7.954446792602539,-4.154786109924316,-4.240443229675293,-5.181422710418701,-10.927129745483398,-4.262921333312988,-6.06287956237793,-7.911689758300781,-8.279668807983398,-6.503976821899414,-4.634165287017822,-4.3072943687438965,-7.227931022644043,-3.5309109687805176,-6.196506977081299,-7.057223320007324,-4.839535236358643,-6.7767181396484375,-4.782458782196045,-5.173086643218994,-5.148260116577148,-6.474668025970459,-7.045830249786377,-6.8330769538879395,-3.2507665157318115,-5.383304119110107,-5.531240940093994,-4.76724910736084,-4.982306003570557,-2.490175247192383,-8.52447509765625,-5.206350326538086,-4.596973419189453,-8.143037796020508,-7.502743244171143,-3.5996127128601074,-3.1505067348480225,-4.502283573150635,-6.632739067077637,-9.811294555664062,-5.566807746887207,0.21051645278930664,-5.429094314575195,-6.422101974487305,-4.654585838317871,-8.110465049743652,-6.150576591491699,-3.421238899230957,-5.653045654296875,-2.7180838584899902,-5.567200660705566,-2.385591745376587,-6.469362735748291,-7.134333610534668,-3.8116707801818848,-2.9478046894073486,-3.6082770824432373,-2.0353798866271973,-6.554582118988037,-6.126589298248291,-4.457681655883789,-7.735702037811279,-6.4336652755737305,-3.826637029647827,-4.8177995681762695,-5.481667995452881,-2.022432804107666,-5.711475372314453,-4.03279972076416,-4.492038726806641,-5.628598690032959,-5.989644527435303,-4.80182409286499,-7.26497220993042,-4.882323741912842,-9.12441349029541,-10.606302261352539,-10.485782623291016,-0.8920001983642578,-3.1166493892669678,-3.0256154537200928,-3.9742465019226074,-1.1344647407531738,-5.613372325897217,-4.215630531311035,-7.389276027679443,-5.666075706481934,-4.759469032287598,-6.192016124725342,-7.459195137023926,-6.032945156097412,-7.9882917404174805,-8.4464750289917,-1.4298222064971924,-9.233048439025879,-5.813747406005859,-5.003689289093018,-8.137388229370117,-1.3100647926330566,-4.294522285461426,-7.8950042724609375,-5.845222473144531,-6.456150531768799,-3.571714162826538,-3.465217351913452,-7.576606750488281,-7.941859722137451,-7.9267578125,-2.738215446472168,-7.211066246032715,-8.11870288848877,-2.5428354740142822,-4.6299591064453125,-4.474435329437256,-7.748103141784668,-3.999894380569458,-4.772665023803711,-2.7248823642730713,-3.324282169342041,-5.149034023284912,-4.672659873962402,-6.693130970001221,-6.42601203918457,-4.699822425842285,-4.755293369293213,-2.920365333557129,-6.160664081573486,-6.425868988037109,-5.939734935760498,-4.669125556945801,-8.558124542236328,-4.80165958404541,-3.0789270401000977,-7.423728942871094,-2.919304847717285,-4.314515113830566,-7.103615760803223,-5.563617706298828,-5.130669116973877,-3.886960983276367,-5.658827304840088,-2.074631929397583,-8.062849044799805,-4.561659812927246,-5.2123703956604,-9.177393913269043,-7.345808982849121,-4.722843170166016,-5.1300554275512695,-5.713542938232422,-4.4308013916015625,-1.9684438705444336,-5.272624492645264,-4.392658233642578,-2.037222385406494,-3.7481110095977783,-6.141972541809082,-6.589566230773926,-1.4112775325775146,-9.049758911132812,-0.9059820175170898,-1.815622329711914,-5.663717746734619,-5.770271301269531,-3.8802967071533203,-2.4721872806549072,-5.936341285705566,-7.051857948303223,-7.748922348022461,-8.779422760009766,-3.8221278190612793,-6.609267234802246,-3.0047450065612793,-6.027502536773682,-8.118816375732422,-0.23999309539794922,-4.416080474853516,-5.321953773498535,-2.7318549156188965,-8.876153945922852,-5.170572757720947,-1.0753898620605469,-8.6068754196167,-8.806008338928223,-6.514641284942627,-2.215498208999634,-3.193490743637085,-8.439168930053711,-5.505091667175293,-5.90566349029541,-10.204246520996094,-10.409587860107422,-6.8577423095703125,-8.250965118408203,-6.162041664123535,-3.470362663269043,-7.286647796630859,-6.410272121429443,-2.375833511352539,-5.4492292404174805,-7.176997184753418,-4.877683639526367,-5.28444766998291,-2.688476085662842,-11.127910614013672,-5.079733371734619,-9.942243576049805,-7.3994622230529785,-8.077275276184082,-4.414538383483887,-3.9022226333618164,-7.871356010437012,-7.247000217437744,-8.342279434204102,-4.595988750457764,-5.199789524078369,-8.019502639770508,-3.0294201374053955,-3.865248203277588,-3.898468494415283,-5.666804790496826,-6.5538434982299805,-4.7859978675842285,-8.306976318359375,-6.357185363769531,-4.269003868103027,-9.042267799377441,-7.718050003051758,-1.6582770347595215,-4.802417278289795,-6.186646938323975,-4.6856207847595215,-3.0495071411132812,-3.0682084560394287,-5.351725101470947,-1.2499127388000488,-5.647239685058594,-7.942544937133789,-7.714549541473389,-6.005688667297363,-3.5182600021362305,-6.56343412399292,-5.9607768058776855,-4.110055446624756,-9.01270866394043,-4.357668876647949],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"#AB63FA","size":3},"mode":"markers","name":"cluster 3","x":[-18.729272842407227,-24.88858985900879,-18.64059829711914,-18.413198471069336,-18.374177932739258,-18.505847930908203,-19.891908645629883,-22.0452880859375,-20.556293487548828,-18.595888137817383,-20.344011306762695,-21.697858810424805,-21.757383346557617,-20.508575439453125,-18.754793167114258,-19.411968231201172,-21.291976928710938,-18.353534698486328,-17.019773483276367,-20.8243350982666,-18.935556411743164,-21.778043746948242,-24.391347885131836,-23.95330810546875,-21.651525497436523,-18.996265411376953,-18.756961822509766,-23.71198081970215,-22.407922744750977,-23.208194732666016,-16.234853744506836,-19.168468475341797,-21.705774307250977,-23.201398849487305,-19.069183349609375,-21.764680862426758,-21.840267181396484,-22.70935821533203,-16.014610290527344,-23.931764602661133,-22.415586471557617,-22.329017639160156,-22.421037673950195,-21.41786003112793,-18.979082107543945,-19.46440887451172,-20.092456817626953,-19.429697036743164,-18.220531463623047,-20.202775955200195,-19.57779312133789,-23.03131866455078,-17.35670280456543,-21.759315490722656,-23.992143630981445,-20.300275802612305,-21.190170288085938,-23.700321197509766,-22.245372772216797,-18.73027992248535,-21.826189041137695,-21.07071304321289,-24.615036010742188,-22.225109100341797,-22.505956649780273,-20.096982955932617,-19.68341827392578,-23.505104064941406,-23.380332946777344,-22.11959457397461,-17.559188842773438,-21.335073471069336,-16.41758155822754,-19.925884246826172,-23.17928123474121,-19.988740921020508,-24.94684410095215,-19.21650505065918,-21.072437286376953,-20.11487579345703,-20.55824089050293,-20.83823585510254,-17.910905838012695,-19.432170867919922,-19.212514877319336,-17.892316818237305,-22.75382423400879,-25.439556121826172,-25.868898391723633,-23.334980010986328,-16.827863693237305,-18.551145553588867,-22.83521842956543,-19.79706573486328,-20.605966567993164,-20.14571189880371,-21.11846923828125,-23.45189666748047,-22.795331954956055,-23.985027313232422,-21.425146102905273,-21.54134750366211,-17.744985580444336,-17.907377243041992,-21.410987854003906,-18.001663208007812,-19.29987144470215,-22.473468780517578,-20.6120548248291,-20.8223934173584,-21.351789474487305,-15.291061401367188,-20.073551177978516,-23.027746200561523,-20.801816940307617,-20.974336624145508,-23.74662208557129,-21.07016372680664,-19.646146774291992,-21.77552032470703,-20.55347442626953,-19.573871612548828,-18.74039077758789,-17.235218048095703,-22.762815475463867,-19.736282348632812,-18.439226150512695,-22.353137969970703,-23.04098892211914,-18.195077896118164,-19.02056121826172,-19.421615600585938,-23.17959213256836,-19.72751235961914,-24.915924072265625,-19.04086685180664,-24.040666580200195,-20.78937530517578,-19.696317672729492,-20.56715965270996,-21.493019104003906,-22.870872497558594,-18.57164192199707,-20.15166473388672,-18.246288299560547,-15.859151840209961,-19.36421012878418,-20.85653305053711,-22.568275451660156,-19.46269416809082,-14.867942810058594,-20.032188415527344,-19.423730850219727,-23.67829704284668,-21.758785247802734,-16.49230194091797,-23.242874145507812,-21.363649368286133,-19.688232421875,-20.075702667236328,-17.748083114624023,-24.18648910522461,-21.707143783569336,-21.320159912109375,-17.836864471435547,-17.53141975402832,-21.578319549560547,-20.090633392333984,-20.899505615234375,-18.848493576049805,-17.17682456970215,-16.21945571899414,-20.710784912109375,-20.37027931213379,-21.095703125,-19.30573272705078,-18.38981819152832,-18.01462173461914,-24.713165283203125,-20.336397171020508,-18.971946716308594,-19.163972854614258,-19.050588607788086,-21.464078903198242,-21.02102279663086,-21.291685104370117,-22.44430160522461,-21.53601837158203,-21.204395294189453,-21.5570011138916,-21.44476890563965,-20.0882568359375,-18.00638198852539,-18.535236358642578,-18.446605682373047,-20.269615173339844,-22.878780364990234,-15.65955638885498,-22.376678466796875,-18.848424911499023,-20.131925582885742,-18.160932540893555,-21.390716552734375,-21.650684356689453,-21.198638916015625,-21.31653594970703,-19.702392578125,-19.534780502319336,-20.976078033447266,-19.479501724243164,-20.13414764404297,-21.86914825439453,-20.0261287689209,-18.784252166748047,-21.113170623779297,-22.704227447509766,-22.278682708740234,-21.06428337097168,-19.73459243774414,-20.478425979614258,-17.266408920288086,-19.435848236083984,-21.369775772094727,-26.125139236450195,-20.925209045410156,-22.034812927246094,-21.304412841796875,-21.861122131347656,-23.065427780151367,-20.346084594726562,-22.81110382080078,-17.335805892944336,-23.915180206298828,-16.913217544555664,-19.844804763793945,-20.419239044189453,-19.4638614654541,-21.124507904052734,-22.996273040771484,-19.658864974975586,-19.083112716674805,-21.826946258544922,-23.277687072753906,-21.13001251220703,-19.31300926208496,-24.088336944580078,-20.70524787902832,-17.94198226928711,-20.78548812866211,-22.760005950927734],"y":[5.096549034118652,7.049332618713379,8.909868240356445,8.016861915588379,11.878761291503906,5.292832374572754,11.711738586425781,8.450275421142578,9.35278034210205,10.393760681152344,10.485952377319336,9.746909141540527,5.429883003234863,8.212258338928223,8.327034950256348,6.187065124511719,4.024733066558838,6.558775901794434,9.063727378845215,8.359020233154297,8.75679874420166,6.895076274871826,6.845462322235107,12.195286750793457,5.006462097167969,7.760155200958252,10.39736557006836,8.46862506866455,9.177868843078613,5.559926986694336,5.79826545715332,7.332425117492676,8.963004112243652,11.87835693359375,12.975247383117676,7.837119102478027,9.866868019104004,11.547372817993164,8.017817497253418,5.493055820465088,9.434844970703125,7.131298542022705,8.015789985656738,10.334327697753906,9.242546081542969,9.196064949035645,11.904093742370605,8.084083557128906,9.587491989135742,10.134839057922363,10.11209487915039,10.894148826599121,12.1345853805542,8.121794700622559,11.4876070022583,10.020998001098633,10.269813537597656,9.597220420837402,6.221399784088135,7.124667167663574,8.715788841247559,8.94090747833252,12.966087341308594,6.627581596374512,11.949153900146484,11.761159896850586,8.439935684204102,8.207571029663086,9.331663131713867,4.251867771148682,6.80094051361084,10.509637832641602,9.417344093322754,9.135666847229004,7.864975929260254,9.490754127502441,11.681961059570312,9.47964096069336,10.242722511291504,10.19731330871582,11.71674919128418,11.744352340698242,11.931480407714844,6.863741874694824,7.533560276031494,13.46342658996582,8.058914184570312,11.127206802368164,5.356972694396973,6.318399429321289,10.66460132598877,12.081207275390625,9.73035717010498,8.702710151672363,8.351639747619629,11.586249351501465,10.585389137268066,9.031097412109375,9.409920692443848,6.520334720611572,7.00762939453125,10.666272163391113,8.969433784484863,9.457207679748535,10.51980972290039,8.959444999694824,6.767205715179443,13.918760299682617,9.046497344970703,5.932514190673828,7.631134510040283,5.709893226623535,9.17736530303955,8.231557846069336,8.079914093017578,11.262250900268555,12.116363525390625,11.351715087890625,7.674842834472656,8.281057357788086,4.5055012702941895,9.775300979614258,14.38041877746582,10.271953582763672,8.96696949005127,11.8857421875,5.7546586990356445,10.225417137145996,8.714073181152344,7.268218994140625,11.230411529541016,7.313052177429199,3.031282901763916,5.163022994995117,12.201239585876465,13.800617218017578,10.899879455566406,9.161162376403809,8.372276306152344,7.217512130737305,9.620133399963379,8.908669471740723,10.88524055480957,12.034449577331543,5.249270439147949,9.776113510131836,10.915929794311523,5.208134651184082,11.109614372253418,8.170943260192871,11.02932357788086,9.32793140411377,5.72052001953125,11.451211929321289,9.364191055297852,11.402604103088379,8.76901626586914,9.361724853515625,11.086835861206055,7.077607154846191,10.700394630432129,12.442825317382812,11.660688400268555,11.688695907592773,3.971463680267334,6.599224090576172,4.920380592346191,10.813061714172363,9.158056259155273,14.124112129211426,6.814990997314453,9.997678756713867,8.436666488647461,10.790520668029785,10.780747413635254,8.582186698913574,9.043107986450195,6.507101058959961,6.132073402404785,11.57738208770752,5.356683731079102,11.510821342468262,7.326781749725342,12.072057723999023,12.863377571105957,8.467535018920898,9.515034675598145,6.873392581939697,7.601968765258789,8.211631774902344,11.103023529052734,10.366954803466797,5.652336120605469,10.336225509643555,8.973592758178711,13.055793762207031,7.338960647583008,7.98708963394165,11.945371627807617,7.605190277099609,9.705709457397461,8.53051471710205,10.059309959411621,7.766096115112305,11.520325660705566,7.021236419677734,7.560451507568359,11.657268524169922,7.911218643188477,5.617547035217285,5.295555591583252,11.085981369018555,10.720305442810059,9.34136962890625,4.919278621673584,11.363151550292969,10.639009475708008,8.66079044342041,9.32776165008545,10.172809600830078,7.683245658874512,7.423390865325928,6.8807573318481445,7.6763410568237305,10.052191734313965,11.467228889465332,10.850114822387695,7.137287616729736,9.252175331115723,10.280884742736816,6.581130504608154,10.401117324829102,7.28129768371582,7.916652202606201,7.520597457885742,6.786144733428955,9.126370429992676,9.697312355041504,11.109733581542969,9.886630058288574,10.103628158569336,6.572298049926758,10.833246231079102,9.192835807800293,9.98744010925293,8.315469741821289,14.385078430175781,9.559182167053223,9.79703426361084,5.094233512878418],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"#FFA15A","size":3},"mode":"markers","name":"cluster 4","x":[-8.600279808044434,-12.10361099243164,-12.14765453338623,-10.046884536743164,-9.201055526733398,-12.007455825805664,-4.321677207946777,-9.431857109069824,-10.79393482208252,-6.351062774658203,-13.856291770935059,-7.982555389404297,-10.778120040893555,-8.85059642791748,-10.491353988647461,-12.326152801513672,-7.175271034240723,-12.458988189697266,-13.064464569091797,-8.235206604003906,-10.59919261932373,-10.732748985290527,-8.94236946105957,-11.100624084472656,-8.151305198669434,-10.83580493927002,-14.114583969116211,-15.892695426940918,-9.881904602050781,-7.548067569732666,-4.985658645629883,-10.445358276367188,-8.225241661071777,-9.147982597351074,-9.012353897094727,-11.588910102844238,-7.2593278884887695,-11.601536750793457,-6.767746448516846,-5.009767055511475,-9.238189697265625,-8.618598937988281,-8.557352066040039,-12.621267318725586,-3.0511579513549805,-11.206414222717285,-8.510185241699219,-8.308615684509277,-10.656183242797852,-13.170201301574707,-10.527009963989258,-7.221179962158203,-13.217294692993164,-12.291364669799805,-8.308812141418457,-8.062202453613281,-10.889323234558105,-8.394033432006836,-8.980734825134277,-8.061798095703125,-13.327995300292969,-10.457670211791992,-10.561936378479004,-12.205080032348633,-10.206729888916016,-8.429023742675781,-12.737086296081543,-12.429974555969238,-7.56069278717041,-7.186188220977783,-9.949129104614258,-10.87218952178955,-7.743781089782715,-8.065786361694336,-6.115677833557129,-8.89757251739502,-9.982120513916016,-12.49746322631836,-16.871959686279297,-8.77431869506836,-8.683637619018555,-9.584238052368164,-8.260108947753906,-8.443947792053223,-9.918534278869629,-15.030573844909668,-16.7659854888916,-8.954389572143555,-12.082758903503418,-8.7927885055542,-9.204771995544434,-12.315057754516602,-10.611921310424805,-11.762124061584473,-9.83623218536377,-7.875572681427002,-6.840780258178711,-7.849913597106934,-7.030721664428711,-9.261911392211914,-11.061655044555664,-12.751651763916016,-9.53978157043457,-5.955102920532227,-10.475480079650879,-7.575878620147705,-5.290384292602539,-7.4312214851379395,-7.686669826507568,-9.265477180480957,-13.562292098999023,-8.067757606506348,-5.928615570068359,-11.14254379272461,-8.080652236938477,-9.174582481384277,-7.377906322479248,-11.867603302001953,-11.04150390625,-11.337408065795898,-10.274253845214844,-10.290769577026367,-8.61528491973877,-9.00598430633545,-11.66600227355957,-10.86557388305664,-10.07654857635498,-10.761791229248047,-9.196762084960938,-9.305646896362305,-13.401457786560059,-7.413378715515137,-12.233810424804688,-9.582377433776855,-11.749908447265625,-8.927349090576172,-8.558415412902832,-8.25199031829834,-13.6466064453125,-10.634471893310547,-9.64920425415039,-10.344839096069336,-9.502182960510254,-5.956055641174316,-10.455148696899414,-11.436091423034668,-7.366311550140381,-11.716115951538086,-11.457780838012695,-10.119546890258789,-6.487796783447266,-7.513344764709473,-9.137932777404785,-7.262057304382324,-8.414298057556152,-5.233402252197266,-9.272754669189453,-11.125605583190918,-9.548826217651367,-7.108059883117676,-8.809890747070312,-8.030457496643066,-6.981706619262695,-7.377267837524414,-13.087952613830566,-12.000344276428223,-7.6092143058776855,-6.271859169006348,-11.963719367980957,-11.865251541137695,-8.496370315551758,-10.722675323486328,-11.15896224975586,-10.42664909362793,-7.754755020141602,-9.915626525878906,-5.2764506340026855,-6.334891319274902,-11.313973426818848,-9.33447551727295,-8.676901817321777,-9.793972969055176,-10.022170066833496,-10.224037170410156,-13.395475387573242,-9.864212989807129,-8.716399192810059,-12.381062507629395,-10.413830757141113,-8.467181205749512,-10.35099983215332,-9.567347526550293,-7.6334028244018555,-10.392940521240234,-8.574857711791992,-9.930715560913086,-5.490166187286377,-8.06926155090332,-13.222980499267578,-7.483623504638672,-7.177618503570557,-5.924283504486084,-7.777842044830322,-9.45787525177002,-7.4070916175842285,-10.088786125183105,-7.039541244506836,-8.80671501159668,-11.783917427062988,-12.611946105957031,-10.853357315063477,-10.662331581115723,-9.261443138122559,-9.977265357971191,-8.961291313171387,-11.526904106140137,-8.45202350616455,-10.37489128112793,-11.229190826416016,-8.945115089416504,-6.900306701660156,-10.512042045593262,-9.616333961486816,-8.230165481567383,-10.43157958984375,-10.326397895812988,-10.076836585998535,-7.697328567504883,-11.054885864257812,-10.01740837097168,-8.35953426361084,-9.028426170349121,-11.740781784057617,-4.273074150085449,-8.872232437133789,-11.219478607177734,-8.559585571289062,-12.894989013671875,-7.532517433166504,-13.100044250488281,-12.649214744567871,-8.306160926818848,-9.870658874511719,-12.515071868896484,-11.063370704650879,-8.09744930267334,-10.042791366577148,-9.475582122802734,-8.004166603088379,-11.936446189880371],"y":[22.743539810180664,24.16919708251953,25.0251522064209,25.900161743164062,21.587554931640625,27.705617904663086,22.87245750427246,23.84690284729004,26.228200912475586,26.56268882751465,26.676258087158203,24.73517417907715,22.20035171508789,24.58065414428711,24.359962463378906,23.589523315429688,27.81822395324707,25.484554290771484,19.327228546142578,25.916807174682617,23.770801544189453,25.56364631652832,24.70351219177246,24.93872833251953,26.459369659423828,25.316364288330078,23.77635955810547,25.07883071899414,26.171701431274414,21.918712615966797,29.12619400024414,24.513723373413086,24.666683197021484,24.338821411132812,21.454212188720703,26.5505428314209,24.956356048583984,23.688236236572266,21.330934524536133,26.833581924438477,21.04785919189453,20.765419006347656,25.685670852661133,24.009382247924805,23.75845718383789,23.716167449951172,28.249034881591797,22.57678985595703,22.686904907226562,26.835844039916992,24.586780548095703,27.812076568603516,20.40938949584961,25.60614776611328,25.73059844970703,20.56486701965332,27.198835372924805,22.551227569580078,25.341751098632812,27.61357879638672,24.30692481994629,27.246902465820312,24.91140365600586,25.521657943725586,22.463455200195312,23.387331008911133,27.042726516723633,23.952205657958984,21.033626556396484,24.695608139038086,28.345739364624023,28.65167808532715,24.607709884643555,27.15869140625,19.741249084472656,20.403369903564453,24.210575103759766,21.159879684448242,22.881038665771484,23.043725967407227,29.53091049194336,25.655502319335938,24.503196716308594,22.72159194946289,22.88680648803711,22.943166732788086,22.309293746948242,27.977127075195312,20.06553077697754,21.433673858642578,26.399377822875977,27.173858642578125,23.00019645690918,26.4375,24.56438446044922,26.510116577148438,22.590972900390625,25.35338592529297,22.346416473388672,25.729711532592773,27.625680923461914,24.76819610595703,23.339092254638672,22.508962631225586,26.104509353637695,18.556913375854492,21.60326385498047,23.777915954589844,24.75299072265625,23.586885452270508,23.766780853271484,25.76375389099121,25.026580810546875,23.963171005249023,26.039113998413086,25.007930755615234,21.547443389892578,24.845178604125977,19.799287796020508,22.864486694335938,25.367431640625,21.888858795166016,26.019668579101562,26.340641021728516,26.414987564086914,23.600156784057617,23.249401092529297,21.754350662231445,19.290672302246094,22.180116653442383,22.14286231994629,26.186405181884766,24.70608901977539,20.765579223632812,27.23318099975586,26.097997665405273,25.306915283203125,23.472421646118164,22.085763931274414,24.30583381652832,24.30274772644043,26.464616775512695,22.98529815673828,23.500106811523438,24.952001571655273,19.976205825805664,27.301612854003906,27.78390121459961,25.43518829345703,30.547283172607422,26.988052368164062,25.167970657348633,21.528928756713867,26.957048416137695,27.557361602783203,25.07265853881836,29.167701721191406,23.4927921295166,25.415115356445312,31.278610229492188,24.98404312133789,20.786903381347656,23.170167922973633,27.227550506591797,25.437793731689453,23.345245361328125,22.90399932861328,23.42783546447754,23.50377082824707,26.9918270111084,24.77071189880371,25.441221237182617,24.401439666748047,24.686203002929688,25.075077056884766,24.92303466796875,23.291086196899414,28.618661880493164,23.902851104736328,26.73432731628418,25.146568298339844,20.78064727783203,29.728137969970703,26.393272399902344,24.7730770111084,30.030563354492188,25.843280792236328,26.564905166625977,25.74042320251465,24.072341918945312,25.759166717529297,26.125762939453125,21.94133758544922,28.726428985595703,25.29500961303711,26.347553253173828,24.46858024597168,28.195083618164062,26.804384231567383,26.84978485107422,21.87255859375,26.37096405029297,24.822145462036133,23.825620651245117,27.145034790039062,25.85413360595703,23.588455200195312,22.668773651123047,24.970367431640625,23.74470329284668,20.167156219482422,25.82902717590332,25.372390747070312,22.63360023498535,23.490890502929688,21.594806671142578,22.37969970703125,26.184295654296875,25.686594009399414,22.98983383178711,23.646930694580078,23.441328048706055,23.168001174926758,26.658031463623047,22.780366897583008,23.858501434326172,19.736209869384766,24.620849609375,23.79120445251465,25.055328369140625,22.651716232299805,21.001781463623047,25.409400939941406,23.543569564819336,26.66622543334961,25.790470123291016,23.636865615844727,24.80181121826172,26.678241729736328,26.70738983154297,22.609853744506836,23.78322982788086,26.075313568115234,24.01766014099121,21.864561080932617,23.54413604736328,22.094404220581055,22.38316535949707,22.771831512451172,22.056541442871094],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"#19D3F3","size":3},"mode":"markers","name":"cluster 5","x":[24.899200439453125,25.795066833496094,26.070402145385742,25.927711486816406,26.66252899169922,22.774890899658203,20.685461044311523,21.782752990722656,25.928184509277344,27.272686004638672,23.010082244873047,26.111072540283203,26.106101989746094,22.6607666015625,22.559585571289062,24.500028610229492,23.088863372802734,23.79488754272461,27.761085510253906,22.000965118408203,20.82413673400879,24.476594924926758,28.03115463256836,27.3532657623291,28.165542602539062,28.796466827392578,23.99007797241211,22.056968688964844,23.61009407043457,22.30701446533203,25.089183807373047,22.002492904663086,27.367473602294922,27.246871948242188,25.25930404663086,24.001001358032227,26.041330337524414,21.625625610351562,24.981874465942383,23.788532257080078,26.80269432067871,23.07561492919922,26.795101165771484,24.452314376831055,29.16944122314453,28.070024490356445,25.093839645385742,23.33034324645996,26.194318771362305,25.2665958404541,27.562015533447266,23.78020668029785,22.557395935058594,24.393325805664062,26.101490020751953,27.476511001586914,26.19685173034668,24.111099243164062,20.387060165405273,21.006633758544922,25.167192459106445,24.56340217590332,23.051406860351562,28.906593322753906,22.50932502746582,24.768089294433594,22.605987548828125,25.35858726501465,26.448427200317383,26.76077651977539,23.56056022644043,22.99807357788086,24.739856719970703,26.94286346435547,27.658893585205078,28.522022247314453,24.90033721923828,24.275232315063477,24.430240631103516,23.79802894592285,21.747955322265625,28.819225311279297,28.93037986755371,22.716203689575195,27.45506477355957,25.689197540283203,23.958393096923828,24.086822509765625,23.32016372680664,27.350196838378906,27.395076751708984,23.01870346069336,22.400943756103516,23.701095581054688,24.106212615966797,21.438077926635742,20.169567108154297,20.630939483642578,23.41472625732422,24.9272403717041,24.787208557128906,21.720869064331055,28.558868408203125,23.521160125732422,25.13656234741211,23.13912010192871,24.775182723999023,27.638830184936523,23.014812469482422,23.67927360534668,27.79462242126465,25.149608612060547,27.190338134765625,26.91124153137207,26.07159996032715,25.266294479370117,25.313432693481445,21.610538482666016,22.321277618408203,21.79326629638672,22.2254695892334,24.561670303344727,25.729812622070312,26.55601692199707,24.761499404907227,24.55518913269043,24.577787399291992,26.31360626220703,25.303955078125,25.912071228027344,27.739866256713867,24.32675552368164,25.038087844848633,19.75543212890625,21.228845596313477,24.750078201293945,23.23501205444336,25.63028907775879,25.343130111694336,26.138517379760742,30.377342224121094,26.338308334350586,26.775650024414062,22.673259735107422,25.929698944091797,29.010038375854492,25.570688247680664,25.132904052734375,27.413604736328125,29.301029205322266,25.478466033935547,26.593420028686523,22.96202278137207,25.76799964904785,26.01138687133789,26.33232879638672,23.242515563964844,25.34132194519043,26.167449951171875,24.88158416748047,27.094654083251953,24.65334129333496,22.707387924194336,27.433595657348633,25.31332778930664,21.087751388549805,26.470483779907227,25.602558135986328,27.10983657836914,28.32958221435547,23.908601760864258,23.664609909057617,26.397850036621094,22.413204193115234,23.011751174926758,24.718311309814453,21.313535690307617,26.970869064331055,26.773643493652344,26.911699295043945,22.799867630004883,24.324865341186523,24.34576988220215,29.44414710998535,25.120370864868164,26.551300048828125,21.735029220581055,22.63677215576172,30.06561851501465,22.052459716796875,25.390186309814453,26.734445571899414,28.65050506591797,25.38561248779297,23.859962463378906,25.764934539794922,26.86248016357422,18.875762939453125,22.709156036376953,22.840129852294922,26.62228012084961,26.380624771118164,24.820100784301758,22.772153854370117,23.607648849487305,23.137004852294922,23.466947555541992,26.885786056518555,21.741676330566406,24.945688247680664,20.279239654541016,25.78778648376465,23.788789749145508,25.024147033691406,25.714275360107422,25.204206466674805,27.750133514404297,20.70173454284668,23.45760726928711,21.71678924560547,27.44124984741211,26.1024169921875,26.064228057861328,24.952377319335938,27.116870880126953,24.09061622619629,29.515384674072266,24.216279983520508,27.689786911010742,27.697851181030273,24.166229248046875,26.182010650634766,21.880571365356445,21.240501403808594,21.066574096679688,27.122303009033203,30.856689453125,22.78137969970703,21.850536346435547,28.399690628051758,23.485631942749023,23.780628204345703,24.41297721862793,28.078693389892578,22.81817626953125,27.078792572021484,20.8679141998291,25.927005767822266,18.548526763916016,24.61690902709961],"y":[3.0319652557373047,8.647820472717285,6.485493183135986,1.8997925519943237,3.5212600231170654,3.314321517944336,3.829113006591797,3.3844125270843506,3.3686046600341797,3.3728227615356445,5.074520587921143,4.550687313079834,3.8484814167022705,2.5673584938049316,9.531397819519043,6.765503883361816,2.8073198795318604,2.4185447692871094,3.6773929595947266,4.295487880706787,2.736370325088501,-0.0961298942565918,2.406905174255371,6.3580522537231445,0.991213321685791,-0.7861075401306152,1.4198143482208252,5.442190647125244,7.63036584854126,1.4205143451690674,4.413945198059082,2.7077383995056152,2.3210105895996094,1.003706455230713,10.02442741394043,-0.8038420677185059,3.422079563140869,4.378314971923828,6.837148666381836,2.6777665615081787,1.8096380233764648,1.2987620830535889,3.622450590133667,2.6359856128692627,6.171802043914795,2.058090925216675,2.671121120452881,2.8334083557128906,4.475510597229004,5.703097820281982,0.796891450881958,4.104783535003662,4.727367401123047,5.064334869384766,3.8951079845428467,4.735243797302246,4.412771701812744,2.0145936012268066,3.5332276821136475,4.008615493774414,9.188220977783203,6.305426597595215,7.566341400146484,6.576202392578125,2.737177610397339,3.6308414936065674,0.6281270980834961,-0.3846395015716553,2.829456090927124,0.036376237869262695,0.6173522472381592,6.221410751342773,5.293233394622803,-1.6498050689697266,1.2223827838897705,1.4708499908447266,2.320496082305908,4.194249629974365,0.6742973327636719,3.8986411094665527,0.1791210174560547,6.081787109375,3.613588809967041,4.302425384521484,2.477876663208008,0.8180911540985107,0.9963235855102539,5.189098834991455,3.562598466873169,7.5441741943359375,4.140510559082031,4.069432735443115,1.1441268920898438,7.160279750823975,4.499896049499512,3.7693867683410645,2.7258567810058594,-0.020596027374267578,4.309000492095947,4.1401519775390625,3.2280688285827637,2.297950267791748,4.5032758712768555,2.8498289585113525,4.085575103759766,7.201923847198486,0.19002175331115723,3.149397611618042,6.872982501983643,0.52272629737854,1.2807166576385498,0.24246501922607422,6.1160664558410645,7.34480094909668,3.399052619934082,5.754234313964844,3.4950406551361084,6.491581916809082,1.3663392066955566,4.147449493408203,4.641958236694336,3.4370739459991455,5.821699619293213,4.045271396636963,2.6516013145446777,4.902143478393555,6.256364822387695,1.9593440294265747,3.167280912399292,-1.6063990592956543,5.547329425811768,4.550471305847168,4.454911231994629,5.346568584442139,3.5084757804870605,-1.9007582664489746,5.555176734924316,4.541838645935059,2.1302638053894043,0.34851932525634766,5.442819118499756,1.049978256225586,-0.21614313125610352,6.830776691436768,2.053988456726074,4.782634258270264,4.4563307762146,7.711938381195068,4.437340259552002,6.186797142028809,2.606409788131714,5.1933465003967285,2.736240863800049,2.1264495849609375,4.2367048263549805,4.338527202606201,4.100940227508545,2.102409601211548,2.6901164054870605,4.439950942993164,3.992133855819702,2.9450674057006836,-1.1087837219238281,3.4456934928894043,2.4532310962677,5.001343250274658,6.772556304931641,-0.2407207489013672,3.6043174266815186,1.4624583721160889,4.777252197265625,4.330015182495117,5.162171840667725,4.42834997177124,7.357789516448975,3.4248228073120117,4.829172134399414,1.725600004196167,5.5704498291015625,5.258073806762695,5.728021621704102,2.576655387878418,1.6610521078109741,5.290985107421875,3.347531318664551,2.8020577430725098,2.438289165496826,11.590871810913086,1.5982846021652222,2.8910014629364014,2.6942076683044434,4.0157012939453125,5.752374172210693,8.181634902954102,0.5997436046600342,1.0372247695922852,3.3782434463500977,5.93861198425293,6.664712905883789,2.9290497303009033,1.2016079425811768,3.935314416885376,2.354177951812744,3.358090400695801,3.8846640586853027,5.460848808288574,1.9229050874710083,4.288052082061768,5.118373394012451,-0.012981891632080078,5.313022613525391,3.4747748374938965,3.0935518741607666,2.2727110385894775,0.42185163497924805,0.9570767879486084,8.854612350463867,5.225698471069336,1.8014941215515137,6.131137847900391,3.9671125411987305,3.7078397274017334,3.9244353771209717,4.110875606536865,4.773287773132324,2.424561023712158,8.203197479248047,4.173276424407959,6.354229927062988,5.656614303588867,2.390371322631836,0.4597814083099365,4.4864912033081055,5.405448913574219,2.6318740844726562,7.523460865020752,7.182490348815918,7.595928192138672,6.12595272064209,1.4430482387542725,2.580331563949585,5.483197212219238,3.344271421432495,3.2679390907287598,5.319302558898926,3.822760581970215,4.575725078582764,6.597330093383789,3.4107120037078857,8.484992027282715],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"}],                        {"template":{"data":{"scatter":[{"marker":{"color":"#d92310"},"type":"scatter"}]},"layout":{"height":576,"paper_bgcolor":"#fcfcfc","plot_bgcolor":"#fcfcfc","width":1024}},"xaxis":{"zeroline":false,"range":[-40,40]},"yaxis":{"zeroline":false,"range":[-40,40]},"updatemenus":[{"buttons":[{"args":[null],"label":"Play","method":"animate"},{"args":[[null],{"frame_duration":0,"frame_redraw":"False","mode":"immediate","transition_duration":0}],"label":"Pause","method":"animate"}],"type":"buttons"}]},                        {"responsive": true}                    ).then(function(){
                            Plotly.addFrames('7d1b0ec9-5d91-4ba4-b13c-dfc5cff3fd45', [{"data":[{"marker":{"color":"#636EFA","size":3},"mode":"markers","name":"cluster 0","x":[0.6106996536254883,4.454596519470215,2.0711617469787598,1.0110520124435425,4.5163893699646,-0.1486372947692871,4.0289177894592285,2.95975923538208,-1.0943694114685059,6.752066612243652,2.888312816619873,4.768091678619385,1.9764769077301025,-1.6155166625976562,-2.1650285720825195,-0.5145149230957031,2.2578015327453613,2.834491491317749,4.584721565246582,0.5921010971069336,-0.688715934753418,6.113814353942871,1.8596506118774414,3.565117835998535,2.0461254119873047,2.412180185317993,-4.187981128692627,1.7536394596099854,6.076658248901367,1.4662054777145386,5.0048909187316895,1.650177240371704,2.742509603500366,1.2938233613967896,-0.3352804183959961,1.1423156261444092,0.4638735055923462,3.4898533821105957,0.6288788318634033,0.12580561637878418,-2.603978157043457,3.7240519523620605,2.163062572479248,6.361776828765869,1.5535951852798462,4.1370134353637695,0.5990724563598633,3.5654516220092773,1.2442047595977783,4.808256149291992,2.729548692703247,1.533890962600708,3.3024158477783203,-0.2711365222930908,3.5784335136413574,3.4738755226135254,-0.07032990455627441,3.8442697525024414,1.1343374252319336,3.8752074241638184,0.6200094223022461,-0.2625694274902344,1.4806886911392212,3.077441453933716,3.7166671752929688,3.6967945098876953,1.9437216520309448,-2.3270368576049805,5.694780349731445,1.703410267829895,2.728020668029785,0.40372776985168457,3.029271125793457,5.021300315856934,7.112307548522949,4.243080139160156,2.595820188522339,1.5233139991760254,4.06235933303833,1.2589422464370728,3.9698963165283203,2.267824172973633,5.580748081207275,2.814542293548584,0.9386806488037109,0.8993861675262451,0.7550551891326904,4.578845024108887,1.3930007219314575,4.2748003005981445,4.01229190826416,3.0979256629943848,3.13167405128479,5.873199939727783,-2.3652734756469727,0.23277902603149414,1.6450698375701904,-0.16131353378295898,5.316432952880859,-0.746211051940918,-3.4459590911865234,4.096480369567871,4.127533912658691,2.5963215827941895,3.8091964721679688,0.47520267963409424,0.9366261959075928,3.342190980911255,-0.08721661567687988,1.2673484086990356,1.8158373832702637,5.756171226501465,3.4982364177703857,5.422142028808594,2.4125044345855713,3.337184429168701,-0.4337937831878662,2.2619690895080566,1.5083262920379639,1.9040424823760986,0.841778039932251,1.4697105884552002,1.0406396389007568,4.13149881362915,3.8440966606140137,1.5222117900848389,4.206725120544434,2.65280818939209,2.458773612976074,1.0481992959976196,4.258362770080566,4.151905059814453,-0.7333433628082275,1.8043519258499146,2.809670925140381,4.118513107299805,2.112030267715454,2.8926684856414795,3.7863731384277344,6.078733444213867,0.17786622047424316,3.2297608852386475,3.361069679260254,4.22938871383667,1.4906213283538818,2.156731367111206,3.407961368560791,1.0653377771377563,6.439641952514648,4.910748481750488,2.0400807857513428,5.018989086151123,3.889838695526123,3.167424201965332,4.468905448913574,4.915773391723633,3.9555795192718506,0.5957375764846802,3.816124439239502,-0.9412333965301514,-1.058197259902954,2.3830742835998535,3.87819766998291,0.6730018854141235,2.681736469268799,-0.7682609558105469,3.026716709136963,3.8628134727478027,3.148106813430786,3.167198657989502,5.090166091918945,2.068650245666504,3.3243465423583984,-0.19996142387390137,7.687468528747559,7.051206588745117,4.482922554016113,2.7472009658813477,1.6230460405349731,4.623526573181152,1.8923182487487793,2.9435620307922363,0.1830892562866211,2.60666561126709,3.119462251663208,6.189139366149902,-0.413712739944458,-1.0135910511016846,4.135379314422607,2.2551188468933105,5.880044937133789,0.2985837459564209,3.565070152282715,4.694297790527344,-0.8904917240142822,-0.025649309158325195,5.0980730056762695,1.2597852945327759,3.941540241241455,2.772353172302246,-0.18204474449157715,-0.41129565238952637,4.791975975036621,2.0827300548553467,2.2586898803710938,-0.25301527976989746,4.837216377258301,4.088098049163818,2.238393783569336,5.4800310134887695,3.3855934143066406,4.921282768249512,1.7489819526672363,1.8883492946624756,3.6563923358917236,4.024860382080078,2.62627911567688,7.209653377532959,-1.1760749816894531,1.2553073167800903,-0.571690559387207,4.939748287200928,0.19209623336791992,2.2359273433685303,1.525259017944336,3.8941426277160645,4.756255149841309,6.353114128112793,3.989452600479126,3.8916399478912354,6.344674110412598,1.3829160928726196,3.179715156555176,1.0047781467437744,6.336634635925293,3.4817066192626953,2.845355749130249,3.630941867828369,2.1003105640411377,5.563776016235352,-1.263171911239624,-1.5524673461914062,3.9684884548187256,5.099576473236084,3.5895919799804688,6.828782081604004,2.7350287437438965,0.5344339609146118,-0.6981027126312256,-0.6902151107788086],"y":[-20.19911766052246,-24.188343048095703,-20.4461612701416,-23.082050323486328,-22.281217575073242,-22.11271858215332,-18.81918716430664,-18.646093368530273,-21.80953025817871,-21.821704864501953,-19.33500862121582,-22.703832626342773,-21.56529426574707,-21.85576057434082,-19.576440811157227,-24.124313354492188,-21.136274337768555,-15.944525718688965,-22.563756942749023,-22.43811798095703,-18.182846069335938,-23.44659423828125,-21.643089294433594,-20.502317428588867,-21.664033889770508,-21.942182540893555,-23.455249786376953,-18.994644165039062,-21.080272674560547,-25.798601150512695,-21.938365936279297,-19.397350311279297,-20.67559242248535,-19.29376220703125,-24.924785614013672,-22.459728240966797,-18.407161712646484,-21.405635833740234,-21.948190689086914,-19.759958267211914,-20.179737091064453,-20.395484924316406,-23.22544288635254,-18.893400192260742,-21.470991134643555,-18.878507614135742,-20.718656539916992,-17.90732765197754,-19.23033905029297,-23.55394744873047,-21.126134872436523,-19.894866943359375,-16.80714225769043,-17.12339210510254,-21.43614959716797,-23.66242790222168,-21.786884307861328,-20.880727767944336,-22.178525924682617,-19.721088409423828,-18.49786949157715,-19.949764251708984,-19.712493896484375,-18.433025360107422,-20.785696029663086,-22.727603912353516,-22.862499237060547,-22.75919532775879,-24.530500411987305,-19.852903366088867,-24.47193717956543,-18.240379333496094,-21.417892456054688,-23.61248779296875,-22.270471572875977,-20.918540954589844,-22.311174392700195,-20.963150024414062,-23.506885528564453,-20.787317276000977,-23.379852294921875,-20.762178421020508,-22.015539169311523,-22.684114456176758,-22.676895141601562,-20.566917419433594,-21.35162353515625,-20.75017547607422,-22.98044776916504,-20.622966766357422,-22.628801345825195,-17.8162784576416,-19.385879516601562,-22.8177433013916,-23.94515609741211,-21.093578338623047,-20.66701889038086,-19.105106353759766,-22.95493507385254,-21.683509826660156,-21.13545036315918,-19.6022891998291,-19.796276092529297,-21.302955627441406,-23.10927391052246,-23.008304595947266,-27.83803367614746,-23.454715728759766,-25.18522071838379,-18.517133712768555,-22.626859664916992,-21.190433502197266,-19.635047912597656,-21.74361228942871,-22.370267868041992,-22.201234817504883,-21.50897789001465,-22.98897933959961,-20.32002067565918,-18.2002010345459,-19.156137466430664,-22.16558265686035,-16.592864990234375,-20.9410343170166,-21.66925048828125,-20.866079330444336,-22.89394187927246,-21.75556182861328,-24.45231819152832,-20.070878982543945,-14.87507152557373,-21.484704971313477,-23.4167423248291,-19.331729888916016,-22.969881057739258,-20.811262130737305,-17.795503616333008,-22.634695053100586,-22.771560668945312,-17.060901641845703,-23.224815368652344,-21.064428329467773,-21.073396682739258,-20.616165161132812,-19.296003341674805,-20.195350646972656,-23.40139389038086,-17.80548858642578,-21.35091209411621,-22.97028923034668,-21.86427116394043,-24.580934524536133,-22.574420928955078,-20.109445571899414,-20.246047973632812,-20.880678176879883,-22.15427589416504,-21.21795082092285,-21.609981536865234,-20.70313835144043,-20.49033546447754,-21.064477920532227,-19.699352264404297,-22.72942543029785,-19.058795928955078,-21.85211944580078,-20.760223388671875,-23.04998779296875,-23.362812042236328,-21.12179946899414,-17.609493255615234,-22.682052612304688,-22.00928497314453,-22.203414916992188,-23.86651611328125,-20.10556411743164,-24.718358993530273,-22.499277114868164,-24.465852737426758,-19.876663208007812,-21.51488494873047,-21.108518600463867,-18.40947914123535,-25.001358032226562,-19.844623565673828,-19.15580940246582,-21.532291412353516,-21.060213088989258,-21.3889217376709,-23.526735305786133,-18.872238159179688,-23.274763107299805,-21.09376335144043,-24.94708824157715,-22.410192489624023,-20.583330154418945,-17.562864303588867,-20.466636657714844,-17.395614624023438,-21.90605926513672,-20.758373260498047,-20.82671546936035,-13.170121192932129,-18.344348907470703,-24.698637008666992,-20.82878875732422,-24.995908737182617,-19.98826026916504,-20.985315322875977,-18.28809356689453,-18.92946434020996,-19.452714920043945,-20.269887924194336,-21.670387268066406,-21.58736801147461,-18.11713981628418,-22.169952392578125,-20.195409774780273,-19.091581344604492,-19.074148178100586,-18.046857833862305,-18.59525489807129,-21.3765926361084,-19.681989669799805,-24.445711135864258,-18.704004287719727,-17.731538772583008,-25.31211280822754,-22.73049545288086,-21.1287784576416,-21.608978271484375,-24.527162551879883,-22.626277923583984,-21.416810989379883,-23.346149444580078,-21.770475387573242,-23.14167594909668,-24.321273803710938,-24.238615036010742,-20.205543518066406,-18.339942932128906,-20.704547882080078,-20.283615112304688,-19.168262481689453,-19.91609001159668,-20.267263412475586,-20.524757385253906,-20.10521697998047,-17.82305145263672,-24.993026733398438],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"#EF553B","size":3},"mode":"markers","name":"cluster 1","x":[9.87704086303711,9.4225435256958,12.610001564025879,8.097820281982422,11.419466972351074,10.570701599121094,10.606629371643066,10.462532043457031,11.331299781799316,11.382926940917969,11.107633590698242,14.95037841796875,13.36851692199707,15.071146011352539,8.195347785949707,8.854641914367676,11.516806602478027,15.112360000610352,9.312355995178223,12.523109436035156,14.841484069824219,15.487283706665039,10.850504875183105,12.387774467468262,11.285183906555176,11.804227828979492,10.544031143188477,13.17994499206543,14.77381420135498,11.45132827758789,9.2578706741333,13.98930835723877,11.58730697631836,9.93220329284668,12.861495971679688,10.736139297485352,9.71112060546875,12.424819946289062,13.16836929321289,11.584234237670898,5.022521495819092,11.749085426330566,11.312202453613281,10.611576080322266,13.377660751342773,9.172962188720703,12.465993881225586,9.5494384765625,18.93263816833496,9.865697860717773,7.6244330406188965,11.1902437210083,13.258797645568848,9.840498924255371,11.613204002380371,11.311509132385254,10.185104370117188,11.270140647888184,12.95288372039795,12.62736701965332,14.55495834350586,11.71548843383789,9.575156211853027,12.831417083740234,7.172362327575684,10.812312126159668,10.21819019317627,11.4874267578125,10.869904518127441,13.847227096557617,11.776945114135742,10.921489715576172,10.18920612335205,10.632547378540039,11.031829833984375,10.981271743774414,14.026257514953613,9.647284507751465,18.137493133544922,11.064699172973633,10.404289245605469,8.46476936340332,14.196146011352539,10.85347843170166,13.36893081665039,8.35534381866455,14.9078950881958,8.62026309967041,6.610985279083252,11.460588455200195,12.1513090133667,13.989845275878906,7.602276802062988,15.068745613098145,15.283571243286133,10.42579460144043,11.41176700592041,10.820887565612793,11.916272163391113,15.157073974609375,10.195613861083984,14.575783729553223,12.577715873718262,8.752012252807617,8.57979679107666,9.327132225036621,11.21414852142334,10.981815338134766,14.445018768310547,6.476677894592285,11.187596321105957,14.057319641113281,11.362394332885742,8.155521392822266,12.265863418579102,11.399274826049805,9.247962951660156,8.10108757019043,12.582670211791992,10.203760147094727,7.150644302368164,11.416135787963867,8.282318115234375,10.93171215057373,9.920757293701172,12.59582233428955,5.954134464263916,11.401212692260742,11.130741119384766,13.161144256591797,8.818209648132324,10.167387008666992,12.14991569519043,11.352355003356934,11.138047218322754,12.394486427307129,12.976234436035156,12.454710006713867,8.250981330871582,15.54655647277832,10.172869682312012,12.827277183532715,8.86609935760498,11.81514835357666,10.636499404907227,9.271520614624023,9.799882888793945,7.832983016967773,10.821706771850586,10.563729286193848,11.64404582977295,12.557385444641113,15.20111083984375,11.216188430786133,12.359991073608398,10.731277465820312,11.025440216064453,13.450078964233398,9.63072395324707,6.332091331481934,10.858210563659668,8.945043563842773,12.985211372375488,15.53884220123291,12.219693183898926,9.413066864013672,12.850086212158203,9.990818977355957,9.073244094848633,8.647806167602539,13.088233947753906,10.905885696411133,12.547986030578613,10.302464485168457,9.783677101135254,12.08859920501709,9.099506378173828,11.802888870239258,8.442436218261719,11.132010459899902,7.804447174072266,14.370488166809082,11.384010314941406,12.67867660522461,9.699455261230469,12.52734661102295,9.536325454711914,9.684154510498047,12.043754577636719,10.859668731689453,8.470977783203125,12.089127540588379,7.456197261810303,8.83816146850586,11.415051460266113,10.549241065979004,6.805138111114502,11.196460723876953,12.749780654907227,12.636879920959473,10.95596694946289,12.731612205505371,11.659228324890137,14.560370445251465,11.841026306152344,7.931714057922363,10.726155281066895,5.702099323272705,12.137916564941406,15.443826675415039,7.3869781494140625,10.457058906555176,11.095139503479004,8.380328178405762,11.541655540466309,9.862030982971191,15.231411933898926,12.802127838134766,12.960502624511719,12.770841598510742,10.196751594543457,10.122230529785156,5.181766986846924,8.951225280761719,10.136018753051758,5.531148910522461,8.604415893554688,7.1645731925964355,12.691882133483887,13.559928894042969,5.198024272918701,14.200967788696289,7.897911071777344,8.21728229522705,11.644851684570312,10.320767402648926,10.415617942810059,15.876169204711914,11.981152534484863,4.864884853363037,9.275575637817383,13.136369705200195,10.784153938293457,12.803083419799805,11.134258270263672,9.973132133483887,11.717573165893555,2.9842147827148438,10.181731224060059,10.367219924926758],"y":[10.734405517578125,9.335786819458008,13.441376686096191,12.330901145935059,10.063323020935059,11.657186508178711,7.365444660186768,8.999773025512695,12.038965225219727,14.764404296875,10.82178020477295,13.4752779006958,11.392098426818848,10.135046005249023,11.840617179870605,9.776314735412598,9.990473747253418,12.085968971252441,13.8656587600708,7.980899333953857,8.725305557250977,12.899062156677246,8.720598220825195,14.300816535949707,11.632344245910645,10.884347915649414,9.99297046661377,10.354414939880371,8.777225494384766,8.373196601867676,8.037626266479492,9.00489616394043,8.283859252929688,12.120036125183105,9.729784965515137,10.034659385681152,13.342782020568848,13.832403182983398,11.30892276763916,9.003535270690918,9.722219467163086,13.053757667541504,12.826997756958008,7.017003059387207,10.649638175964355,13.679852485656738,9.408282279968262,12.128579139709473,13.113380432128906,12.83919906616211,12.413917541503906,11.668290138244629,6.153925895690918,11.991576194763184,10.793174743652344,12.52327823638916,12.068902969360352,9.22436237335205,10.30783748626709,5.3423004150390625,10.344483375549316,14.47255802154541,7.237033367156982,12.807012557983398,12.02662467956543,12.13406753540039,12.714216232299805,11.554706573486328,11.308341026306152,7.09832763671875,13.935083389282227,11.023280143737793,11.676339149475098,10.078460693359375,8.887862205505371,8.004937171936035,12.172079086303711,8.344019889831543,10.546194076538086,10.278603553771973,9.850561141967773,6.540694236755371,14.094623565673828,13.03080940246582,12.026119232177734,9.844781875610352,14.854454040527344,9.092710494995117,7.083795547485352,13.150472640991211,8.925386428833008,9.54330825805664,12.065450668334961,13.750585556030273,10.335978507995605,14.149402618408203,10.169922828674316,14.469759941101074,12.803152084350586,10.56090259552002,10.896300315856934,10.610678672790527,10.40132999420166,10.194389343261719,9.682408332824707,8.019926071166992,12.813308715820312,7.141301155090332,8.150213241577148,10.157896995544434,10.739936828613281,8.905439376831055,12.959728240966797,14.031454086303711,13.927950859069824,15.988347053527832,8.539347648620605,11.02241039276123,11.853888511657715,10.494282722473145,11.071870803833008,12.508426666259766,10.966612815856934,11.251618385314941,12.862878799438477,11.168071746826172,11.423723220825195,7.485688209533691,14.271825790405273,13.000264167785645,12.808016777038574,8.910547256469727,4.895911693572998,7.373517036437988,14.97317886352539,11.791913032531738,10.086353302001953,12.438005447387695,12.250608444213867,8.70448112487793,9.40768051147461,8.550436019897461,8.311664581298828,11.452293395996094,9.780439376831055,12.431370735168457,12.913421630859375,8.143282890319824,9.135396957397461,11.134149551391602,6.741981029510498,9.244380950927734,10.749717712402344,14.637189865112305,12.528155326843262,9.443887710571289,14.947844505310059,7.758157730102539,13.048039436340332,10.627683639526367,10.81523609161377,10.374131202697754,9.01569652557373,14.85327434539795,8.898709297180176,11.091988563537598,8.544888496398926,13.079777717590332,12.462029457092285,6.712798595428467,9.902111053466797,10.244808197021484,7.307023048400879,9.82799243927002,9.81595230102539,12.278499603271484,12.8430757522583,14.464896202087402,10.822654724121094,10.515324592590332,11.292708396911621,10.368403434753418,9.722280502319336,11.41006088256836,14.371049880981445,12.479593276977539,11.51334285736084,9.181450843811035,11.381587028503418,11.955004692077637,8.314370155334473,13.114908218383789,14.425192832946777,11.066229820251465,9.404319763183594,14.337783813476562,7.97857666015625,9.011209487915039,15.631593704223633,11.388583183288574,14.366738319396973,11.034764289855957,8.076003074645996,9.505967140197754,12.511550903320312,8.819988250732422,7.850310325622559,19.094078063964844,13.645238876342773,12.414156913757324,10.631463050842285,10.430276870727539,9.743120193481445,10.801138877868652,9.165804862976074,13.029094696044922,10.357752799987793,8.63907241821289,6.381320953369141,9.96885871887207,8.676495552062988,14.108659744262695,10.252354621887207,10.053375244140625,9.217528343200684,11.634859085083008,10.610607147216797,13.862188339233398,14.077072143554688,12.144886016845703,6.061443328857422,9.93949031829834,14.236883163452148,11.515740394592285,9.876175880432129,12.265829086303711,4.3912739753723145,8.761274337768555,10.186405181884766,11.717260360717773,12.657522201538086,6.422496318817139,12.245983123779297,11.363253593444824,9.916359901428223,9.322500228881836,12.07647705078125,10.818828582763672,10.659802436828613,6.526799201965332],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"#00CC96","size":3},"mode":"markers","name":"cluster 2","x":[-23.496248245239258,-19.102161407470703,-20.136016845703125,-16.482664108276367,-16.349597930908203,-19.713245391845703,-18.65350341796875,-13.829034805297852,-18.291528701782227,-19.674604415893555,-18.3510799407959,-17.09149932861328,-17.577880859375,-20.840408325195312,-17.026063919067383,-18.766075134277344,-18.991413116455078,-15.431722640991211,-15.667441368103027,-16.49349594116211,-18.01854705810547,-18.996410369873047,-20.137609481811523,-21.6656551361084,-18.331777572631836,-18.460737228393555,-17.945327758789062,-14.076920509338379,-22.975576400756836,-20.383657455444336,-16.282447814941406,-17.628402709960938,-18.828432083129883,-23.07760238647461,-17.44770622253418,-18.911293029785156,-17.204139709472656,-15.39111614227295,-15.860858917236328,-19.705379486083984,-20.822938919067383,-16.104167938232422,-15.548961639404297,-18.728506088256836,-15.924317359924316,-16.256725311279297,-18.9020938873291,-17.295326232910156,-19.94478988647461,-20.530868530273438,-18.124982833862305,-18.22002410888672,-16.544612884521484,-15.984344482421875,-21.301803588867188,-20.72646713256836,-19.2755126953125,-21.295223236083984,-17.879823684692383,-21.625612258911133,-23.16211700439453,-19.277111053466797,-21.854236602783203,-21.373796463012695,-20.612863540649414,-19.7716007232666,-18.101654052734375,-13.594627380371094,-15.992204666137695,-19.817270278930664,-19.524595260620117,-16.413419723510742,-19.63754653930664,-20.195295333862305,-18.661693572998047,-23.166744232177734,-25.767223358154297,-17.47901725769043,-20.107112884521484,-18.87466049194336,-14.021196365356445,-23.9616641998291,-17.631515502929688,-16.309242248535156,-21.137012481689453,-21.122529983520508,-17.305912017822266,-19.604686737060547,-16.410690307617188,-16.7831974029541,-20.05327606201172,-15.291223526000977,-19.566797256469727,-25.432048797607422,-22.283740997314453,-19.412412643432617,-16.233285903930664,-18.915956497192383,-17.18501853942871,-22.00074005126953,-17.94850730895996,-20.63845443725586,-17.973421096801758,-21.913644790649414,-19.405956268310547,-18.921245574951172,-14.960383415222168,-14.140716552734375,-19.379091262817383,-15.164407730102539,-19.23599624633789,-17.085628509521484,-24.900020599365234,-17.930837631225586,-15.017277717590332,-18.39430046081543,-18.29949951171875,-19.81678009033203,-16.499399185180664,-21.1153621673584,-20.64909553527832,-16.530471801757812,-18.152694702148438,-19.830692291259766,-17.068748474121094,-16.368009567260742,-22.440576553344727,-24.575397491455078,-20.936744689941406,-16.465473175048828,-16.289825439453125,-16.341110229492188,-19.04955291748047,-23.555402755737305,-19.5102481842041,-18.35858917236328,-17.890913009643555,-19.442907333374023,-14.255441665649414,-19.23705291748047,-19.83909034729004,-18.734312057495117,-19.848955154418945,-21.674922943115234,-17.039281845092773,-16.802776336669922,-19.45977210998535,-16.507213592529297,-17.979259490966797,-21.164430618286133,-16.55664825439453,-19.571863174438477,-18.527997970581055,-16.438730239868164,-18.222482681274414,-17.97646713256836,-18.645158767700195,-21.904409408569336,-17.995407104492188,-14.85053539276123,-15.628301620483398,-19.503097534179688,-19.802371978759766,-23.55690574645996,-20.865854263305664,-21.97210121154785,-17.619220733642578,-17.55777931213379,-18.90250015258789,-19.595022201538086,-22.55715560913086,-18.7069149017334,-15.946229934692383,-17.116031646728516,-22.056068420410156,-18.132993698120117,-17.69864273071289,-18.772863388061523,-17.69382095336914,-18.974563598632812,-18.597265243530273,-19.086097717285156,-19.763315200805664,-19.784135818481445,-19.49692153930664,-22.22881317138672,-19.871448516845703,-19.91254425048828,-17.67487335205078,-14.83010482788086,-16.431415557861328,-18.875661849975586,-19.289630889892578,-19.932777404785156,-18.83257293701172,-17.950456619262695,-19.316957473754883,-17.2662410736084,-17.319856643676758,-20.356781005859375,-20.86867904663086,-19.766145706176758,-19.172279357910156,-20.614933013916016,-17.56839942932129,-19.70578384399414,-21.004182815551758,-14.180909156799316,-16.228187561035156,-22.096920013427734,-16.230567932128906,-14.014081954956055,-18.133859634399414,-18.271791458129883,-14.894996643066406,-20.85570526123047,-20.33222770690918,-19.34016990661621,-19.300125122070312,-18.69086265563965,-20.986141204833984,-19.05849266052246,-21.730819702148438,-19.53059959411621,-18.280332565307617,-16.290420532226562,-22.174251556396484,-19.60970687866211,-20.317441940307617,-16.59217643737793,-16.612627029418945,-16.287940979003906,-21.55924415588379,-15.447280883789062,-18.48925018310547,-20.813961029052734,-16.740083694458008,-13.458377838134766,-17.664106369018555,-18.019548416137695,-16.611682891845703,-16.419452667236328,-18.20526885986328,-20.381473541259766,-19.548341751098633,-17.654024124145508,-19.76431655883789,-19.859495162963867,-19.523746490478516,-17.158977508544922],"y":[-2.3969573974609375,-5.214266777038574,-3.7279253005981445,-5.133577823638916,-7.954446792602539,-4.154786109924316,-4.240443229675293,-5.181422710418701,-10.927129745483398,-4.262921333312988,-6.06287956237793,-7.911689758300781,-8.279668807983398,-6.503976821899414,-4.634165287017822,-4.3072943687438965,-7.227931022644043,-3.5309109687805176,-6.196506977081299,-7.057223320007324,-4.839535236358643,-6.7767181396484375,-4.782458782196045,-5.173086643218994,-5.148260116577148,-6.474668025970459,-7.045830249786377,-6.8330769538879395,-3.2507665157318115,-5.383304119110107,-5.531240940093994,-4.76724910736084,-4.982306003570557,-2.490175247192383,-8.52447509765625,-5.206350326538086,-4.596973419189453,-8.143037796020508,-7.502743244171143,-3.5996127128601074,-3.1505067348480225,-4.502283573150635,-6.632739067077637,-9.811294555664062,-5.566807746887207,0.21051645278930664,-5.429094314575195,-6.422101974487305,-4.654585838317871,-8.110465049743652,-6.150576591491699,-3.421238899230957,-5.653045654296875,-2.7180838584899902,-5.567200660705566,-2.385591745376587,-6.469362735748291,-7.134333610534668,-3.8116707801818848,-2.9478046894073486,-3.6082770824432373,-2.0353798866271973,-6.554582118988037,-6.126589298248291,-4.457681655883789,-7.735702037811279,-6.4336652755737305,-3.826637029647827,-4.8177995681762695,-5.481667995452881,-2.022432804107666,-5.711475372314453,-4.03279972076416,-4.492038726806641,-5.628598690032959,-5.989644527435303,-4.80182409286499,-7.26497220993042,-4.882323741912842,-9.12441349029541,-10.606302261352539,-10.485782623291016,-0.8920001983642578,-3.1166493892669678,-3.0256154537200928,-3.9742465019226074,-1.1344647407531738,-5.613372325897217,-4.215630531311035,-7.389276027679443,-5.666075706481934,-4.759469032287598,-6.192016124725342,-7.459195137023926,-6.032945156097412,-7.9882917404174805,-8.4464750289917,-1.4298222064971924,-9.233048439025879,-5.813747406005859,-5.003689289093018,-8.137388229370117,-1.3100647926330566,-4.294522285461426,-7.8950042724609375,-5.845222473144531,-6.456150531768799,-3.571714162826538,-3.465217351913452,-7.576606750488281,-7.941859722137451,-7.9267578125,-2.738215446472168,-7.211066246032715,-8.11870288848877,-2.5428354740142822,-4.6299591064453125,-4.474435329437256,-7.748103141784668,-3.999894380569458,-4.772665023803711,-2.7248823642730713,-3.324282169342041,-5.149034023284912,-4.672659873962402,-6.693130970001221,-6.42601203918457,-4.699822425842285,-4.755293369293213,-2.920365333557129,-6.160664081573486,-6.425868988037109,-5.939734935760498,-4.669125556945801,-8.558124542236328,-4.80165958404541,-3.0789270401000977,-7.423728942871094,-2.919304847717285,-4.314515113830566,-7.103615760803223,-5.563617706298828,-5.130669116973877,-3.886960983276367,-5.658827304840088,-2.074631929397583,-8.062849044799805,-4.561659812927246,-5.2123703956604,-9.177393913269043,-7.345808982849121,-4.722843170166016,-5.1300554275512695,-5.713542938232422,-4.4308013916015625,-1.9684438705444336,-5.272624492645264,-4.392658233642578,-2.037222385406494,-3.7481110095977783,-6.141972541809082,-6.589566230773926,-1.4112775325775146,-9.049758911132812,-0.9059820175170898,-1.815622329711914,-5.663717746734619,-5.770271301269531,-3.8802967071533203,-2.4721872806549072,-5.936341285705566,-7.051857948303223,-7.748922348022461,-8.779422760009766,-3.8221278190612793,-6.609267234802246,-3.0047450065612793,-6.027502536773682,-8.118816375732422,-0.23999309539794922,-4.416080474853516,-5.321953773498535,-2.7318549156188965,-8.876153945922852,-5.170572757720947,-1.0753898620605469,-8.6068754196167,-8.806008338928223,-6.514641284942627,-2.215498208999634,-3.193490743637085,-8.439168930053711,-5.505091667175293,-5.90566349029541,-10.204246520996094,-10.409587860107422,-6.8577423095703125,-8.250965118408203,-6.162041664123535,-3.470362663269043,-7.286647796630859,-6.410272121429443,-2.375833511352539,-5.4492292404174805,-7.176997184753418,-4.877683639526367,-5.28444766998291,-2.688476085662842,-11.127910614013672,-5.079733371734619,-9.942243576049805,-7.3994622230529785,-8.077275276184082,-4.414538383483887,-3.9022226333618164,-7.871356010437012,-7.247000217437744,-8.342279434204102,-4.595988750457764,-5.199789524078369,-8.019502639770508,-3.0294201374053955,-3.865248203277588,-3.898468494415283,-5.666804790496826,-6.5538434982299805,-4.7859978675842285,-8.306976318359375,-6.357185363769531,-4.269003868103027,-9.042267799377441,-7.718050003051758,-1.6582770347595215,-4.802417278289795,-6.186646938323975,-4.6856207847595215,-3.0495071411132812,-3.0682084560394287,-5.351725101470947,-1.2499127388000488,-5.647239685058594,-7.942544937133789,-7.714549541473389,-6.005688667297363,-3.5182600021362305,-6.56343412399292,-5.9607768058776855,-4.110055446624756,-9.01270866394043,-4.357668876647949],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"#AB63FA","size":3},"mode":"markers","name":"cluster 3","x":[-18.729272842407227,-24.88858985900879,-18.64059829711914,-18.413198471069336,-18.374177932739258,-18.505847930908203,-19.891908645629883,-22.0452880859375,-20.556293487548828,-18.595888137817383,-20.344011306762695,-21.697858810424805,-21.757383346557617,-20.508575439453125,-18.754793167114258,-19.411968231201172,-21.291976928710938,-18.353534698486328,-17.019773483276367,-20.8243350982666,-18.935556411743164,-21.778043746948242,-24.391347885131836,-23.95330810546875,-21.651525497436523,-18.996265411376953,-18.756961822509766,-23.71198081970215,-22.407922744750977,-23.208194732666016,-16.234853744506836,-19.168468475341797,-21.705774307250977,-23.201398849487305,-19.069183349609375,-21.764680862426758,-21.840267181396484,-22.70935821533203,-16.014610290527344,-23.931764602661133,-22.415586471557617,-22.329017639160156,-22.421037673950195,-21.41786003112793,-18.979082107543945,-19.46440887451172,-20.092456817626953,-19.429697036743164,-18.220531463623047,-20.202775955200195,-19.57779312133789,-23.03131866455078,-17.35670280456543,-21.759315490722656,-23.992143630981445,-20.300275802612305,-21.190170288085938,-23.700321197509766,-22.245372772216797,-18.73027992248535,-21.826189041137695,-21.07071304321289,-24.615036010742188,-22.225109100341797,-22.505956649780273,-20.096982955932617,-19.68341827392578,-23.505104064941406,-23.380332946777344,-22.11959457397461,-17.559188842773438,-21.335073471069336,-16.41758155822754,-19.925884246826172,-23.17928123474121,-19.988740921020508,-24.94684410095215,-19.21650505065918,-21.072437286376953,-20.11487579345703,-20.55824089050293,-20.83823585510254,-17.910905838012695,-19.432170867919922,-19.212514877319336,-17.892316818237305,-22.75382423400879,-25.439556121826172,-25.868898391723633,-23.334980010986328,-16.827863693237305,-18.551145553588867,-22.83521842956543,-19.79706573486328,-20.605966567993164,-20.14571189880371,-21.11846923828125,-23.45189666748047,-22.795331954956055,-23.985027313232422,-21.425146102905273,-21.54134750366211,-17.744985580444336,-17.907377243041992,-21.410987854003906,-18.001663208007812,-19.29987144470215,-22.473468780517578,-20.6120548248291,-20.8223934173584,-21.351789474487305,-15.291061401367188,-20.073551177978516,-23.027746200561523,-20.801816940307617,-20.974336624145508,-23.74662208557129,-21.07016372680664,-19.646146774291992,-21.77552032470703,-20.55347442626953,-19.573871612548828,-18.74039077758789,-17.235218048095703,-22.762815475463867,-19.736282348632812,-18.439226150512695,-22.353137969970703,-23.04098892211914,-18.195077896118164,-19.02056121826172,-19.421615600585938,-23.17959213256836,-19.72751235961914,-24.915924072265625,-19.04086685180664,-24.040666580200195,-20.78937530517578,-19.696317672729492,-20.56715965270996,-21.493019104003906,-22.870872497558594,-18.57164192199707,-20.15166473388672,-18.246288299560547,-15.859151840209961,-19.36421012878418,-20.85653305053711,-22.568275451660156,-19.46269416809082,-14.867942810058594,-20.032188415527344,-19.423730850219727,-23.67829704284668,-21.758785247802734,-16.49230194091797,-23.242874145507812,-21.363649368286133,-19.688232421875,-20.075702667236328,-17.748083114624023,-24.18648910522461,-21.707143783569336,-21.320159912109375,-17.836864471435547,-17.53141975402832,-21.578319549560547,-20.090633392333984,-20.899505615234375,-18.848493576049805,-17.17682456970215,-16.21945571899414,-20.710784912109375,-20.37027931213379,-21.095703125,-19.30573272705078,-18.38981819152832,-18.01462173461914,-24.713165283203125,-20.336397171020508,-18.971946716308594,-19.163972854614258,-19.050588607788086,-21.464078903198242,-21.02102279663086,-21.291685104370117,-22.44430160522461,-21.53601837158203,-21.204395294189453,-21.5570011138916,-21.44476890563965,-20.0882568359375,-18.00638198852539,-18.535236358642578,-18.446605682373047,-20.269615173339844,-22.878780364990234,-15.65955638885498,-22.376678466796875,-18.848424911499023,-20.131925582885742,-18.160932540893555,-21.390716552734375,-21.650684356689453,-21.198638916015625,-21.31653594970703,-19.702392578125,-19.534780502319336,-20.976078033447266,-19.479501724243164,-20.13414764404297,-21.86914825439453,-20.0261287689209,-18.784252166748047,-21.113170623779297,-22.704227447509766,-22.278682708740234,-21.06428337097168,-19.73459243774414,-20.478425979614258,-17.266408920288086,-19.435848236083984,-21.369775772094727,-26.125139236450195,-20.925209045410156,-22.034812927246094,-21.304412841796875,-21.861122131347656,-23.065427780151367,-20.346084594726562,-22.81110382080078,-17.335805892944336,-23.915180206298828,-16.913217544555664,-19.844804763793945,-20.419239044189453,-19.4638614654541,-21.124507904052734,-22.996273040771484,-19.658864974975586,-19.083112716674805,-21.826946258544922,-23.277687072753906,-21.13001251220703,-19.31300926208496,-24.088336944580078,-20.70524787902832,-17.94198226928711,-20.78548812866211,-22.760005950927734],"y":[5.096549034118652,7.049332618713379,8.909868240356445,8.016861915588379,11.878761291503906,5.292832374572754,11.711738586425781,8.450275421142578,9.35278034210205,10.393760681152344,10.485952377319336,9.746909141540527,5.429883003234863,8.212258338928223,8.327034950256348,6.187065124511719,4.024733066558838,6.558775901794434,9.063727378845215,8.359020233154297,8.75679874420166,6.895076274871826,6.845462322235107,12.195286750793457,5.006462097167969,7.760155200958252,10.39736557006836,8.46862506866455,9.177868843078613,5.559926986694336,5.79826545715332,7.332425117492676,8.963004112243652,11.87835693359375,12.975247383117676,7.837119102478027,9.866868019104004,11.547372817993164,8.017817497253418,5.493055820465088,9.434844970703125,7.131298542022705,8.015789985656738,10.334327697753906,9.242546081542969,9.196064949035645,11.904093742370605,8.084083557128906,9.587491989135742,10.134839057922363,10.11209487915039,10.894148826599121,12.1345853805542,8.121794700622559,11.4876070022583,10.020998001098633,10.269813537597656,9.597220420837402,6.221399784088135,7.124667167663574,8.715788841247559,8.94090747833252,12.966087341308594,6.627581596374512,11.949153900146484,11.761159896850586,8.439935684204102,8.207571029663086,9.331663131713867,4.251867771148682,6.80094051361084,10.509637832641602,9.417344093322754,9.135666847229004,7.864975929260254,9.490754127502441,11.681961059570312,9.47964096069336,10.242722511291504,10.19731330871582,11.71674919128418,11.744352340698242,11.931480407714844,6.863741874694824,7.533560276031494,13.46342658996582,8.058914184570312,11.127206802368164,5.356972694396973,6.318399429321289,10.66460132598877,12.081207275390625,9.73035717010498,8.702710151672363,8.351639747619629,11.586249351501465,10.585389137268066,9.031097412109375,9.409920692443848,6.520334720611572,7.00762939453125,10.666272163391113,8.969433784484863,9.457207679748535,10.51980972290039,8.959444999694824,6.767205715179443,13.918760299682617,9.046497344970703,5.932514190673828,7.631134510040283,5.709893226623535,9.17736530303955,8.231557846069336,8.079914093017578,11.262250900268555,12.116363525390625,11.351715087890625,7.674842834472656,8.281057357788086,4.5055012702941895,9.775300979614258,14.38041877746582,10.271953582763672,8.96696949005127,11.8857421875,5.7546586990356445,10.225417137145996,8.714073181152344,7.268218994140625,11.230411529541016,7.313052177429199,3.031282901763916,5.163022994995117,12.201239585876465,13.800617218017578,10.899879455566406,9.161162376403809,8.372276306152344,7.217512130737305,9.620133399963379,8.908669471740723,10.88524055480957,12.034449577331543,5.249270439147949,9.776113510131836,10.915929794311523,5.208134651184082,11.109614372253418,8.170943260192871,11.02932357788086,9.32793140411377,5.72052001953125,11.451211929321289,9.364191055297852,11.402604103088379,8.76901626586914,9.361724853515625,11.086835861206055,7.077607154846191,10.700394630432129,12.442825317382812,11.660688400268555,11.688695907592773,3.971463680267334,6.599224090576172,4.920380592346191,10.813061714172363,9.158056259155273,14.124112129211426,6.814990997314453,9.997678756713867,8.436666488647461,10.790520668029785,10.780747413635254,8.582186698913574,9.043107986450195,6.507101058959961,6.132073402404785,11.57738208770752,5.356683731079102,11.510821342468262,7.326781749725342,12.072057723999023,12.863377571105957,8.467535018920898,9.515034675598145,6.873392581939697,7.601968765258789,8.211631774902344,11.103023529052734,10.366954803466797,5.652336120605469,10.336225509643555,8.973592758178711,13.055793762207031,7.338960647583008,7.98708963394165,11.945371627807617,7.605190277099609,9.705709457397461,8.53051471710205,10.059309959411621,7.766096115112305,11.520325660705566,7.021236419677734,7.560451507568359,11.657268524169922,7.911218643188477,5.617547035217285,5.295555591583252,11.085981369018555,10.720305442810059,9.34136962890625,4.919278621673584,11.363151550292969,10.639009475708008,8.66079044342041,9.32776165008545,10.172809600830078,7.683245658874512,7.423390865325928,6.8807573318481445,7.6763410568237305,10.052191734313965,11.467228889465332,10.850114822387695,7.137287616729736,9.252175331115723,10.280884742736816,6.581130504608154,10.401117324829102,7.28129768371582,7.916652202606201,7.520597457885742,6.786144733428955,9.126370429992676,9.697312355041504,11.109733581542969,9.886630058288574,10.103628158569336,6.572298049926758,10.833246231079102,9.192835807800293,9.98744010925293,8.315469741821289,14.385078430175781,9.559182167053223,9.79703426361084,5.094233512878418],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"#FFA15A","size":3},"mode":"markers","name":"cluster 4","x":[-8.600279808044434,-12.10361099243164,-12.14765453338623,-10.046884536743164,-9.201055526733398,-12.007455825805664,-4.321677207946777,-9.431857109069824,-10.79393482208252,-6.351062774658203,-13.856291770935059,-7.982555389404297,-10.778120040893555,-8.85059642791748,-10.491353988647461,-12.326152801513672,-7.175271034240723,-12.458988189697266,-13.064464569091797,-8.235206604003906,-10.59919261932373,-10.732748985290527,-8.94236946105957,-11.100624084472656,-8.151305198669434,-10.83580493927002,-14.114583969116211,-15.892695426940918,-9.881904602050781,-7.548067569732666,-4.985658645629883,-10.445358276367188,-8.225241661071777,-9.147982597351074,-9.012353897094727,-11.588910102844238,-7.2593278884887695,-11.601536750793457,-6.767746448516846,-5.009767055511475,-9.238189697265625,-8.618598937988281,-8.557352066040039,-12.621267318725586,-3.0511579513549805,-11.206414222717285,-8.510185241699219,-8.308615684509277,-10.656183242797852,-13.170201301574707,-10.527009963989258,-7.221179962158203,-13.217294692993164,-12.291364669799805,-8.308812141418457,-8.062202453613281,-10.889323234558105,-8.394033432006836,-8.980734825134277,-8.061798095703125,-13.327995300292969,-10.457670211791992,-10.561936378479004,-12.205080032348633,-10.206729888916016,-8.429023742675781,-12.737086296081543,-12.429974555969238,-7.56069278717041,-7.186188220977783,-9.949129104614258,-10.87218952178955,-7.743781089782715,-8.065786361694336,-6.115677833557129,-8.89757251739502,-9.982120513916016,-12.49746322631836,-16.871959686279297,-8.77431869506836,-8.683637619018555,-9.584238052368164,-8.260108947753906,-8.443947792053223,-9.918534278869629,-15.030573844909668,-16.7659854888916,-8.954389572143555,-12.082758903503418,-8.7927885055542,-9.204771995544434,-12.315057754516602,-10.611921310424805,-11.762124061584473,-9.83623218536377,-7.875572681427002,-6.840780258178711,-7.849913597106934,-7.030721664428711,-9.261911392211914,-11.061655044555664,-12.751651763916016,-9.53978157043457,-5.955102920532227,-10.475480079650879,-7.575878620147705,-5.290384292602539,-7.4312214851379395,-7.686669826507568,-9.265477180480957,-13.562292098999023,-8.067757606506348,-5.928615570068359,-11.14254379272461,-8.080652236938477,-9.174582481384277,-7.377906322479248,-11.867603302001953,-11.04150390625,-11.337408065795898,-10.274253845214844,-10.290769577026367,-8.61528491973877,-9.00598430633545,-11.66600227355957,-10.86557388305664,-10.07654857635498,-10.761791229248047,-9.196762084960938,-9.305646896362305,-13.401457786560059,-7.413378715515137,-12.233810424804688,-9.582377433776855,-11.749908447265625,-8.927349090576172,-8.558415412902832,-8.25199031829834,-13.6466064453125,-10.634471893310547,-9.64920425415039,-10.344839096069336,-9.502182960510254,-5.956055641174316,-10.455148696899414,-11.436091423034668,-7.366311550140381,-11.716115951538086,-11.457780838012695,-10.119546890258789,-6.487796783447266,-7.513344764709473,-9.137932777404785,-7.262057304382324,-8.414298057556152,-5.233402252197266,-9.272754669189453,-11.125605583190918,-9.548826217651367,-7.108059883117676,-8.809890747070312,-8.030457496643066,-6.981706619262695,-7.377267837524414,-13.087952613830566,-12.000344276428223,-7.6092143058776855,-6.271859169006348,-11.963719367980957,-11.865251541137695,-8.496370315551758,-10.722675323486328,-11.15896224975586,-10.42664909362793,-7.754755020141602,-9.915626525878906,-5.2764506340026855,-6.334891319274902,-11.313973426818848,-9.33447551727295,-8.676901817321777,-9.793972969055176,-10.022170066833496,-10.224037170410156,-13.395475387573242,-9.864212989807129,-8.716399192810059,-12.381062507629395,-10.413830757141113,-8.467181205749512,-10.35099983215332,-9.567347526550293,-7.6334028244018555,-10.392940521240234,-8.574857711791992,-9.930715560913086,-5.490166187286377,-8.06926155090332,-13.222980499267578,-7.483623504638672,-7.177618503570557,-5.924283504486084,-7.777842044830322,-9.45787525177002,-7.4070916175842285,-10.088786125183105,-7.039541244506836,-8.80671501159668,-11.783917427062988,-12.611946105957031,-10.853357315063477,-10.662331581115723,-9.261443138122559,-9.977265357971191,-8.961291313171387,-11.526904106140137,-8.45202350616455,-10.37489128112793,-11.229190826416016,-8.945115089416504,-6.900306701660156,-10.512042045593262,-9.616333961486816,-8.230165481567383,-10.43157958984375,-10.326397895812988,-10.076836585998535,-7.697328567504883,-11.054885864257812,-10.01740837097168,-8.35953426361084,-9.028426170349121,-11.740781784057617,-4.273074150085449,-8.872232437133789,-11.219478607177734,-8.559585571289062,-12.894989013671875,-7.532517433166504,-13.100044250488281,-12.649214744567871,-8.306160926818848,-9.870658874511719,-12.515071868896484,-11.063370704650879,-8.09744930267334,-10.042791366577148,-9.475582122802734,-8.004166603088379,-11.936446189880371],"y":[22.743539810180664,24.16919708251953,25.0251522064209,25.900161743164062,21.587554931640625,27.705617904663086,22.87245750427246,23.84690284729004,26.228200912475586,26.56268882751465,26.676258087158203,24.73517417907715,22.20035171508789,24.58065414428711,24.359962463378906,23.589523315429688,27.81822395324707,25.484554290771484,19.327228546142578,25.916807174682617,23.770801544189453,25.56364631652832,24.70351219177246,24.93872833251953,26.459369659423828,25.316364288330078,23.77635955810547,25.07883071899414,26.171701431274414,21.918712615966797,29.12619400024414,24.513723373413086,24.666683197021484,24.338821411132812,21.454212188720703,26.5505428314209,24.956356048583984,23.688236236572266,21.330934524536133,26.833581924438477,21.04785919189453,20.765419006347656,25.685670852661133,24.009382247924805,23.75845718383789,23.716167449951172,28.249034881591797,22.57678985595703,22.686904907226562,26.835844039916992,24.586780548095703,27.812076568603516,20.40938949584961,25.60614776611328,25.73059844970703,20.56486701965332,27.198835372924805,22.551227569580078,25.341751098632812,27.61357879638672,24.30692481994629,27.246902465820312,24.91140365600586,25.521657943725586,22.463455200195312,23.387331008911133,27.042726516723633,23.952205657958984,21.033626556396484,24.695608139038086,28.345739364624023,28.65167808532715,24.607709884643555,27.15869140625,19.741249084472656,20.403369903564453,24.210575103759766,21.159879684448242,22.881038665771484,23.043725967407227,29.53091049194336,25.655502319335938,24.503196716308594,22.72159194946289,22.88680648803711,22.943166732788086,22.309293746948242,27.977127075195312,20.06553077697754,21.433673858642578,26.399377822875977,27.173858642578125,23.00019645690918,26.4375,24.56438446044922,26.510116577148438,22.590972900390625,25.35338592529297,22.346416473388672,25.729711532592773,27.625680923461914,24.76819610595703,23.339092254638672,22.508962631225586,26.104509353637695,18.556913375854492,21.60326385498047,23.777915954589844,24.75299072265625,23.586885452270508,23.766780853271484,25.76375389099121,25.026580810546875,23.963171005249023,26.039113998413086,25.007930755615234,21.547443389892578,24.845178604125977,19.799287796020508,22.864486694335938,25.367431640625,21.888858795166016,26.019668579101562,26.340641021728516,26.414987564086914,23.600156784057617,23.249401092529297,21.754350662231445,19.290672302246094,22.180116653442383,22.14286231994629,26.186405181884766,24.70608901977539,20.765579223632812,27.23318099975586,26.097997665405273,25.306915283203125,23.472421646118164,22.085763931274414,24.30583381652832,24.30274772644043,26.464616775512695,22.98529815673828,23.500106811523438,24.952001571655273,19.976205825805664,27.301612854003906,27.78390121459961,25.43518829345703,30.547283172607422,26.988052368164062,25.167970657348633,21.528928756713867,26.957048416137695,27.557361602783203,25.07265853881836,29.167701721191406,23.4927921295166,25.415115356445312,31.278610229492188,24.98404312133789,20.786903381347656,23.170167922973633,27.227550506591797,25.437793731689453,23.345245361328125,22.90399932861328,23.42783546447754,23.50377082824707,26.9918270111084,24.77071189880371,25.441221237182617,24.401439666748047,24.686203002929688,25.075077056884766,24.92303466796875,23.291086196899414,28.618661880493164,23.902851104736328,26.73432731628418,25.146568298339844,20.78064727783203,29.728137969970703,26.393272399902344,24.7730770111084,30.030563354492188,25.843280792236328,26.564905166625977,25.74042320251465,24.072341918945312,25.759166717529297,26.125762939453125,21.94133758544922,28.726428985595703,25.29500961303711,26.347553253173828,24.46858024597168,28.195083618164062,26.804384231567383,26.84978485107422,21.87255859375,26.37096405029297,24.822145462036133,23.825620651245117,27.145034790039062,25.85413360595703,23.588455200195312,22.668773651123047,24.970367431640625,23.74470329284668,20.167156219482422,25.82902717590332,25.372390747070312,22.63360023498535,23.490890502929688,21.594806671142578,22.37969970703125,26.184295654296875,25.686594009399414,22.98983383178711,23.646930694580078,23.441328048706055,23.168001174926758,26.658031463623047,22.780366897583008,23.858501434326172,19.736209869384766,24.620849609375,23.79120445251465,25.055328369140625,22.651716232299805,21.001781463623047,25.409400939941406,23.543569564819336,26.66622543334961,25.790470123291016,23.636865615844727,24.80181121826172,26.678241729736328,26.70738983154297,22.609853744506836,23.78322982788086,26.075313568115234,24.01766014099121,21.864561080932617,23.54413604736328,22.094404220581055,22.38316535949707,22.771831512451172,22.056541442871094],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"#19D3F3","size":3},"mode":"markers","name":"cluster 5","x":[24.899200439453125,25.795066833496094,26.070402145385742,25.927711486816406,26.66252899169922,22.774890899658203,20.685461044311523,21.782752990722656,25.928184509277344,27.272686004638672,23.010082244873047,26.111072540283203,26.106101989746094,22.6607666015625,22.559585571289062,24.500028610229492,23.088863372802734,23.79488754272461,27.761085510253906,22.000965118408203,20.82413673400879,24.476594924926758,28.03115463256836,27.3532657623291,28.165542602539062,28.796466827392578,23.99007797241211,22.056968688964844,23.61009407043457,22.30701446533203,25.089183807373047,22.002492904663086,27.367473602294922,27.246871948242188,25.25930404663086,24.001001358032227,26.041330337524414,21.625625610351562,24.981874465942383,23.788532257080078,26.80269432067871,23.07561492919922,26.795101165771484,24.452314376831055,29.16944122314453,28.070024490356445,25.093839645385742,23.33034324645996,26.194318771362305,25.2665958404541,27.562015533447266,23.78020668029785,22.557395935058594,24.393325805664062,26.101490020751953,27.476511001586914,26.19685173034668,24.111099243164062,20.387060165405273,21.006633758544922,25.167192459106445,24.56340217590332,23.051406860351562,28.906593322753906,22.50932502746582,24.768089294433594,22.605987548828125,25.35858726501465,26.448427200317383,26.76077651977539,23.56056022644043,22.99807357788086,24.739856719970703,26.94286346435547,27.658893585205078,28.522022247314453,24.90033721923828,24.275232315063477,24.430240631103516,23.79802894592285,21.747955322265625,28.819225311279297,28.93037986755371,22.716203689575195,27.45506477355957,25.689197540283203,23.958393096923828,24.086822509765625,23.32016372680664,27.350196838378906,27.395076751708984,23.01870346069336,22.400943756103516,23.701095581054688,24.106212615966797,21.438077926635742,20.169567108154297,20.630939483642578,23.41472625732422,24.9272403717041,24.787208557128906,21.720869064331055,28.558868408203125,23.521160125732422,25.13656234741211,23.13912010192871,24.775182723999023,27.638830184936523,23.014812469482422,23.67927360534668,27.79462242126465,25.149608612060547,27.190338134765625,26.91124153137207,26.07159996032715,25.266294479370117,25.313432693481445,21.610538482666016,22.321277618408203,21.79326629638672,22.2254695892334,24.561670303344727,25.729812622070312,26.55601692199707,24.761499404907227,24.55518913269043,24.577787399291992,26.31360626220703,25.303955078125,25.912071228027344,27.739866256713867,24.32675552368164,25.038087844848633,19.75543212890625,21.228845596313477,24.750078201293945,23.23501205444336,25.63028907775879,25.343130111694336,26.138517379760742,30.377342224121094,26.338308334350586,26.775650024414062,22.673259735107422,25.929698944091797,29.010038375854492,25.570688247680664,25.132904052734375,27.413604736328125,29.301029205322266,25.478466033935547,26.593420028686523,22.96202278137207,25.76799964904785,26.01138687133789,26.33232879638672,23.242515563964844,25.34132194519043,26.167449951171875,24.88158416748047,27.094654083251953,24.65334129333496,22.707387924194336,27.433595657348633,25.31332778930664,21.087751388549805,26.470483779907227,25.602558135986328,27.10983657836914,28.32958221435547,23.908601760864258,23.664609909057617,26.397850036621094,22.413204193115234,23.011751174926758,24.718311309814453,21.313535690307617,26.970869064331055,26.773643493652344,26.911699295043945,22.799867630004883,24.324865341186523,24.34576988220215,29.44414710998535,25.120370864868164,26.551300048828125,21.735029220581055,22.63677215576172,30.06561851501465,22.052459716796875,25.390186309814453,26.734445571899414,28.65050506591797,25.38561248779297,23.859962463378906,25.764934539794922,26.86248016357422,18.875762939453125,22.709156036376953,22.840129852294922,26.62228012084961,26.380624771118164,24.820100784301758,22.772153854370117,23.607648849487305,23.137004852294922,23.466947555541992,26.885786056518555,21.741676330566406,24.945688247680664,20.279239654541016,25.78778648376465,23.788789749145508,25.024147033691406,25.714275360107422,25.204206466674805,27.750133514404297,20.70173454284668,23.45760726928711,21.71678924560547,27.44124984741211,26.1024169921875,26.064228057861328,24.952377319335938,27.116870880126953,24.09061622619629,29.515384674072266,24.216279983520508,27.689786911010742,27.697851181030273,24.166229248046875,26.182010650634766,21.880571365356445,21.240501403808594,21.066574096679688,27.122303009033203,30.856689453125,22.78137969970703,21.850536346435547,28.399690628051758,23.485631942749023,23.780628204345703,24.41297721862793,28.078693389892578,22.81817626953125,27.078792572021484,20.8679141998291,25.927005767822266,18.548526763916016,24.61690902709961],"y":[3.0319652557373047,8.647820472717285,6.485493183135986,1.8997925519943237,3.5212600231170654,3.314321517944336,3.829113006591797,3.3844125270843506,3.3686046600341797,3.3728227615356445,5.074520587921143,4.550687313079834,3.8484814167022705,2.5673584938049316,9.531397819519043,6.765503883361816,2.8073198795318604,2.4185447692871094,3.6773929595947266,4.295487880706787,2.736370325088501,-0.0961298942565918,2.406905174255371,6.3580522537231445,0.991213321685791,-0.7861075401306152,1.4198143482208252,5.442190647125244,7.63036584854126,1.4205143451690674,4.413945198059082,2.7077383995056152,2.3210105895996094,1.003706455230713,10.02442741394043,-0.8038420677185059,3.422079563140869,4.378314971923828,6.837148666381836,2.6777665615081787,1.8096380233764648,1.2987620830535889,3.622450590133667,2.6359856128692627,6.171802043914795,2.058090925216675,2.671121120452881,2.8334083557128906,4.475510597229004,5.703097820281982,0.796891450881958,4.104783535003662,4.727367401123047,5.064334869384766,3.8951079845428467,4.735243797302246,4.412771701812744,2.0145936012268066,3.5332276821136475,4.008615493774414,9.188220977783203,6.305426597595215,7.566341400146484,6.576202392578125,2.737177610397339,3.6308414936065674,0.6281270980834961,-0.3846395015716553,2.829456090927124,0.036376237869262695,0.6173522472381592,6.221410751342773,5.293233394622803,-1.6498050689697266,1.2223827838897705,1.4708499908447266,2.320496082305908,4.194249629974365,0.6742973327636719,3.8986411094665527,0.1791210174560547,6.081787109375,3.613588809967041,4.302425384521484,2.477876663208008,0.8180911540985107,0.9963235855102539,5.189098834991455,3.562598466873169,7.5441741943359375,4.140510559082031,4.069432735443115,1.1441268920898438,7.160279750823975,4.499896049499512,3.7693867683410645,2.7258567810058594,-0.020596027374267578,4.309000492095947,4.1401519775390625,3.2280688285827637,2.297950267791748,4.5032758712768555,2.8498289585113525,4.085575103759766,7.201923847198486,0.19002175331115723,3.149397611618042,6.872982501983643,0.52272629737854,1.2807166576385498,0.24246501922607422,6.1160664558410645,7.34480094909668,3.399052619934082,5.754234313964844,3.4950406551361084,6.491581916809082,1.3663392066955566,4.147449493408203,4.641958236694336,3.4370739459991455,5.821699619293213,4.045271396636963,2.6516013145446777,4.902143478393555,6.256364822387695,1.9593440294265747,3.167280912399292,-1.6063990592956543,5.547329425811768,4.550471305847168,4.454911231994629,5.346568584442139,3.5084757804870605,-1.9007582664489746,5.555176734924316,4.541838645935059,2.1302638053894043,0.34851932525634766,5.442819118499756,1.049978256225586,-0.21614313125610352,6.830776691436768,2.053988456726074,4.782634258270264,4.4563307762146,7.711938381195068,4.437340259552002,6.186797142028809,2.606409788131714,5.1933465003967285,2.736240863800049,2.1264495849609375,4.2367048263549805,4.338527202606201,4.100940227508545,2.102409601211548,2.6901164054870605,4.439950942993164,3.992133855819702,2.9450674057006836,-1.1087837219238281,3.4456934928894043,2.4532310962677,5.001343250274658,6.772556304931641,-0.2407207489013672,3.6043174266815186,1.4624583721160889,4.777252197265625,4.330015182495117,5.162171840667725,4.42834997177124,7.357789516448975,3.4248228073120117,4.829172134399414,1.725600004196167,5.5704498291015625,5.258073806762695,5.728021621704102,2.576655387878418,1.6610521078109741,5.290985107421875,3.347531318664551,2.8020577430725098,2.438289165496826,11.590871810913086,1.5982846021652222,2.8910014629364014,2.6942076683044434,4.0157012939453125,5.752374172210693,8.181634902954102,0.5997436046600342,1.0372247695922852,3.3782434463500977,5.93861198425293,6.664712905883789,2.9290497303009033,1.2016079425811768,3.935314416885376,2.354177951812744,3.358090400695801,3.8846640586853027,5.460848808288574,1.9229050874710083,4.288052082061768,5.118373394012451,-0.012981891632080078,5.313022613525391,3.4747748374938965,3.0935518741607666,2.2727110385894775,0.42185163497924805,0.9570767879486084,8.854612350463867,5.225698471069336,1.8014941215515137,6.131137847900391,3.9671125411987305,3.7078397274017334,3.9244353771209717,4.110875606536865,4.773287773132324,2.424561023712158,8.203197479248047,4.173276424407959,6.354229927062988,5.656614303588867,2.390371322631836,0.4597814083099365,4.4864912033081055,5.405448913574219,2.6318740844726562,7.523460865020752,7.182490348815918,7.595928192138672,6.12595272064209,1.4430482387542725,2.580331563949585,5.483197212219238,3.344271421432495,3.2679390907287598,5.319302558898926,3.822760581970215,4.575725078582764,6.597330093383789,3.4107120037078857,8.484992027282715],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"}]},{"data":[{"marker":{"color":"#636EFA","size":3},"mode":"markers","name":"cluster 0","x":[1.6946265697479248,3.449998617172241,2.3729336261749268,1.9416052103042603,3.4232354164123535,1.393724799156189,3.203889846801758,2.742619037628174,0.9621626734733582,4.264341831207275,2.7116641998291016,3.4931559562683105,2.3637421131134033,0.7502619624137878,0.5140782594680786,1.3128371238708496,2.467108964920044,2.726853609085083,3.3970415592193604,1.8129693269729614,1.168636679649353,3.9801809787750244,2.325812578201294,2.972182512283325,2.4004223346710205,2.5505640506744385,-0.5080786943435669,2.2283055782318115,3.9053497314453125,2.2120308876037598,3.4893414974212646,2.197722911834717,2.6455559730529785,2.0543947219848633,1.4671787023544312,2.0673391819000244,1.7018321752548218,2.925679922103882,1.859802484512329,1.6141977310180664,0.49830183386802673,2.999140739440918,2.480736494064331,4.006897449493408,2.224219799041748,3.160285711288452,1.8546350002288818,2.966703176498413,2.0785467624664307,3.4128572940826416,2.648806095123291,2.206836700439453,2.9089088439941406,1.4336549043655396,2.9363622665405273,2.9449901580810547,1.644398808479309,3.014716148376465,2.11179780960083,3.026470422744751,1.8596433401107788,1.5716087818145752,2.214670419692993,2.7771472930908203,2.9622044563293457,2.977346181869507,2.4111127853393555,0.7618668675422668,3.719949960708618,2.295081615447998,2.6981592178344727,1.8176337480545044,2.736699342727661,3.408546209335327,4.097562789916992,3.1021454334259033,2.605257034301758,2.258788585662842,3.0681488513946533,2.176664113998413,3.029879570007324,2.4986486434936523,3.4964356422424316,2.667665481567383,2.0924112796783447,2.0721352100372314,2.0405476093292236,3.1822311878204346,2.259921073913574,3.0854318141937256,3.005093812942505,2.7969536781311035,2.761613607406616,3.544318437576294,0.8529166579246521,1.885594367980957,2.3264403343200684,1.7199219465255737,3.3416733741760254,1.5913722515106201,0.5495020747184753,3.0220677852630615,3.016310691833496,2.586745262145996,2.9057140350341797,2.019304037094116,2.019484281539917,2.7870585918426514,1.8434600830078125,2.2048447132110596,2.3979060649871826,3.420743465423584,2.8256638050079346,3.288011312484741,2.5389583110809326,2.7542002201080322,1.7702414989471436,2.512371063232422,2.307831287384033,2.410545587539673,2.1187453269958496,2.324117660522461,2.1551711559295654,2.945241689682007,2.864262580871582,2.3277230262756348,2.9510087966918945,2.5914838314056396,2.5753321647644043,2.2084193229675293,3.576427459716797,2.9279403686523438,1.7457350492477417,2.409273624420166,2.63500714302063,2.9217264652252197,2.5131676197052,2.643481731414795,2.831210136413574,3.8069164752960205,2.0308752059936523,2.713686227798462,2.738316774368286,2.9315781593322754,2.330852508544922,2.486298084259033,2.7511332035064697,2.2206685543060303,3.4792003631591797,3.0461947917938232,2.455667734146118,3.1273677349090576,2.8069722652435303,2.697984457015991,2.962015390396118,3.024524450302124,2.7957241535186768,2.140803575515747,2.7702906131744385,1.7410404682159424,1.7314332723617554,2.5178892612457275,2.8300509452819824,2.193343162536621,2.6096065044403076,1.878253698348999,2.636425018310547,2.766038656234741,2.6407313346862793,2.6477770805358887,3.275813341140747,2.4590258598327637,2.6642305850982666,2.0397214889526367,3.8388824462890625,3.5617833137512207,2.892345905303955,2.5714948177337646,2.391604423522949,2.9260976314544678,2.4415640830993652,2.607224941253662,2.0695953369140625,2.563575506210327,2.6549837589263916,3.3067409992218018,2.0315568447113037,1.911465048789978,2.7747244834899902,2.5050957202911377,3.198904037475586,2.2129693031311035,2.6859564781188965,2.9133646488189697,2.0121095180511475,2.1648502349853516,3.098203182220459,2.3815953731536865,2.8553466796875,2.583845376968384,2.1685073375701904,2.1501879692077637,3.8614518642425537,2.5223875045776367,2.5367186069488525,2.2027230262756348,2.9115684032440186,2.7739622592926025,2.5361804962158203,3.066636085510254,2.689459800720215,2.881826162338257,2.475058078765869,2.498260021209717,2.6855835914611816,2.77927827835083,2.5728089809417725,3.263051986694336,1.9935120344161987,2.4182701110839844,2.110403060913086,2.862842559814453,2.3278934955596924,2.545283317565918,2.464959144592285,2.721184492111206,2.8335001468658447,3.1609034538269043,2.702655553817749,2.685124397277832,2.9480550289154053,2.4472742080688477,2.613926887512207,2.427957773208618,2.910409927368164,2.6316471099853516,2.5788679122924805,2.631870746612549,2.508378028869629,2.804633617401123,2.0834224224090576,2.1646745204925537,2.6558806896209717,2.742758274078369,2.6148931980133057,2.848088502883911,2.5519447326660156,2.401672601699829,2.2792060375213623,2.2420196533203125],"y":[-20.78610610961914,-22.398971557617188,-20.914709091186523,-21.91057777404785,-21.66291618347168,-21.51350212097168,-20.268638610839844,-20.216014862060547,-21.380203247070312,-21.513076782226562,-20.512157440185547,-21.819744110107422,-21.34463119506836,-21.38899803161621,-20.501529693603516,-22.269506454467773,-21.191009521484375,-19.07061195373535,-21.74657440185547,-21.613126754760742,-20.02367401123047,-22.10400390625,-21.350706100463867,-20.969181060791016,-21.361974716186523,-21.465110778808594,-22.06197738647461,-20.40784454345703,-21.180397033691406,-22.87186622619629,-21.50389862060547,-20.57219886779785,-21.041126251220703,-20.54086685180664,-22.4803524017334,-21.612083435058594,-20.219520568847656,-21.303709030151367,-21.42768669128418,-20.700531005859375,-20.79828643798828,-20.95842170715332,-21.872081756591797,-20.31779670715332,-21.287094116210938,-20.416881561279297,-21.03209686279297,-20.076547622680664,-20.57390785217285,-22.04358673095703,-21.205764770507812,-20.807540893554688,-19.673297882080078,-19.82783317565918,-21.308837890625,-22.010562896728516,-21.35736846923828,-21.13275718688965,-21.48708724975586,-20.770605087280273,-20.378089904785156,-20.819568634033203,-20.785449981689453,-20.39082145690918,-21.122148513793945,-21.70020294189453,-21.696765899658203,-21.658658981323242,-22.364282608032227,-20.849689483642578,-22.194488525390625,-20.36215591430664,-21.294260025024414,-21.9702091217041,-21.572914123535156,-21.15321922302246,-21.525487899780273,-21.158227920532227,-21.883634567260742,-21.11046600341797,-21.829654693603516,-21.11017417907715,-21.445404052734375,-21.607295989990234,-21.58856773376465,-21.04619598388672,-21.244075775146484,-21.086017608642578,-21.663700103759766,-21.057340621948242,-21.590354919433594,-20.262195587158203,-20.756179809570312,-21.670854568481445,-21.991043090820312,-21.17201805114746,-21.090423583984375,-20.667747497558594,-21.684301376342773,-21.3138427734375,-21.11836814880371,-20.80900764465332,-20.868244171142578,-21.252674102783203,-21.69295310974121,-21.637887954711914,-23.49968910217285,-21.765769958496094,-22.238492965698242,-20.580352783203125,-21.533187866210938,-21.184926986694336,-20.863258361816406,-21.339921951293945,-21.475404739379883,-21.440658569335938,-21.252796173095703,-21.59950828552246,-21.027490615844727,-20.52918815612793,-20.781038284301758,-21.412921905517578,-20.053823471069336,-21.155458450317383,-21.3143253326416,-21.153533935546875,-21.5880069732666,-21.325592041015625,-21.92909049987793,-20.99647331237793,-18.872333526611328,-21.253009796142578,-21.64813232421875,-20.853683471679688,-21.55528450012207,-21.112478256225586,-20.518156051635742,-21.478647232055664,-21.50851058959961,-19.923219680786133,-21.565340042114258,-21.167688369750977,-21.16850471496582,-21.068004608154297,-20.872211456298828,-21.036710739135742,-21.625194549560547,-20.59202003479004,-21.168167114257812,-21.545501708984375,-21.31072425842285,-21.959199905395508,-21.424419403076172,-21.009016036987305,-20.991405487060547,-21.09759521484375,-21.347339630126953,-21.20339012145996,-21.249305725097656,-21.098363876342773,-21.064701080322266,-21.17884063720703,-20.921052932739258,-21.445514678955078,-20.860958099365234,-21.29085350036621,-21.13347625732422,-21.505151748657227,-21.54643440246582,-21.17691421508789,-20.373516082763672,-21.412731170654297,-21.30141258239746,-21.327178955078125,-21.86045265197754,-20.812671661376953,-21.842405319213867,-21.362932205200195,-21.701045989990234,-20.939922332763672,-21.220561981201172,-21.1634521484375,-20.771873474121094,-21.785940170288086,-20.998600006103516,-20.712705612182617,-21.211671829223633,-21.136688232421875,-21.19127655029297,-21.47712516784668,-20.701736450195312,-21.429153442382812,-21.155410766601562,-21.768978118896484,-21.2914981842041,-21.080453872680664,-20.50115203857422,-21.09111785888672,-20.604705810546875,-21.249418258666992,-21.103071212768555,-21.10801887512207,-17.54497718811035,-20.840980529785156,-21.6018123626709,-21.115680694580078,-21.677776336669922,-21.025733947753906,-21.15434455871582,-20.728164672851562,-20.935171127319336,-20.97151756286621,-21.09917449951172,-21.227930068969727,-21.217927932739258,-20.840961456298828,-21.27079963684082,-21.020103454589844,-20.885765075683594,-20.994483947753906,-20.83262825012207,-20.91411781311035,-21.206768035888672,-21.077322006225586,-21.501840591430664,-20.984357833862305,-20.880023956298828,-21.741382598876953,-21.312536239624023,-21.19350242614746,-21.225488662719727,-21.466764450073242,-21.28557586669922,-21.199525833129883,-21.347515106201172,-21.2202091217041,-21.30464744567871,-21.373323440551758,-21.351539611816406,-21.092405319213867,-20.906835556030273,-21.136032104492188,-21.11936378479004,-21.0457820892334,-21.113126754760742,-21.124452590942383,-21.150630950927734,-21.125343322753906,-20.96417999267578,-21.453123092651367],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"#EF553B","size":3},"mode":"markers","name":"cluster 1","x":[10.553921699523926,10.378192901611328,11.677305221557617,9.76516056060791,11.228522300720215,10.852045059204102,10.936358451843262,10.848250389099121,11.160809516906738,11.177790641784668,11.086302757263184,12.732450485229492,12.019720077514648,12.866479873657227,9.845115661621094,10.165964126586914,11.27199935913086,12.764793395996094,10.379088401794434,11.732418060302734,12.765474319458008,12.87234878540039,11.03215217590332,11.526556968688965,11.153594017028809,11.360498428344727,10.894035339355469,11.902581214904785,12.668740272521973,11.266735076904297,10.382909774780273,12.255353927612305,11.316174507141113,10.6468505859375,11.758978843688965,10.968881607055664,10.567042350769043,11.527205467224121,11.820052146911621,11.288623809814453,8.06213092803955,11.279064178466797,11.128617286682129,10.943465232849121,11.892148971557617,10.355629920959473,11.576713562011719,10.511497497558594,15.913922309875488,10.637694358825684,9.707133293151855,11.10561466217041,12.0292329788208,10.644925117492676,11.2578763961792,11.146879196166992,10.769599914550781,11.154306411743164,11.724708557128906,11.759297370910645,12.35037612915039,11.284743309020996,10.5274076461792,11.63113784790039,9.534015655517578,10.978789329528809,10.788853645324707,11.196309089660645,11.002007484436035,12.166753768920898,11.288334846496582,11.02209186553955,10.786494255065918,10.937630653381348,11.072771072387695,11.059539794921875,12.039098739624023,10.596759796142578,15.357443809509277,11.083370208740234,10.876011848449707,10.060815811157227,12.093324661254883,10.996378898620605,11.774632453918457,10.139411926269531,12.340705871582031,10.260533332824707,9.196358680725098,11.163867950439453,11.441466331481934,12.043437004089355,9.849756240844727,12.309586524963379,12.509374618530273,10.862445831298828,11.183209419250488,10.974650382995605,11.28494930267334,12.382393836975098,10.832682609558105,12.110004425048828,11.483365058898926,10.37495231628418,10.324080467224121,10.592535972595215,11.095077514648438,11.124641418457031,12.197379112243652,9.373515129089355,11.11252498626709,11.94969367980957,11.12753963470459,10.132634162902832,11.342312812805176,11.11259937286377,10.59852409362793,10.211478233337402,11.423558235168457,10.872918128967285,9.833968162536621,11.137648582458496,10.324847221374512,11.047890663146973,10.782092094421387,11.428747177124023,9.23951244354248,11.218369483947754,11.050278663635254,11.52939510345459,10.494760513305664,10.894204139709473,11.551217079162598,11.20985221862793,11.042498588562012,11.350503921508789,11.514573097229004,11.341403007507324,10.360342979431152,12.553485870361328,10.900530815124512,11.507806777954102,10.562841415405273,11.215763092041016,11.002530097961426,10.667011260986328,10.78979778289795,10.242466926574707,11.060234069824219,10.982453346252441,11.299104690551758,11.412644386291504,12.082005500793457,11.071557998657227,11.304062843322754,11.033889770507812,11.017111778259277,11.665783882141113,10.76292610168457,9.687395095825195,11.04201602935791,10.665197372436523,11.474325180053711,12.198394775390625,11.315717697143555,10.77605152130127,11.443704605102539,10.869242668151855,10.697967529296875,10.52572250366211,11.447805404663086,11.062193870544434,11.396424293518066,10.962074279785156,10.874069213867188,11.248862266540527,10.715302467346191,11.199419021606445,10.606327056884766,11.109124183654785,10.4501371383667,11.697257041931152,11.148107528686523,11.332337379455566,10.827033996582031,11.299649238586426,10.855655670166016,10.885908126831055,11.229434967041016,11.059819221496582,10.637429237365723,11.22687816619873,10.234177589416504,10.756370544433594,11.156249046325684,11.006500244140625,10.10341739654541,11.128985404968262,11.35232925415039,11.300151824951172,11.051115989685059,11.308767318725586,11.197009086608887,11.690791130065918,11.16855239868164,10.595367431640625,11.073407173156738,6.6604461669921875,11.196741104125977,11.813139915466309,10.482831954956055,11.021352767944336,11.102421760559082,10.738703727722168,11.164712905883789,10.927050590515137,11.755099296569824,11.31787395477295,11.440556526184082,11.274033546447754,11.006196022033691,10.944647789001465,9.432446479797363,10.864757537841797,11.010411262512207,9.830744743347168,10.841902732849121,10.458699226379395,11.239252090454102,11.328508377075195,9.075081825256348,11.437505722045898,10.664111137390137,10.81592845916748,11.136358261108398,11.018789291381836,11.04726791381836,12.124147415161133,11.160086631774902,9.763992309570312,10.939802169799805,11.361539840698242,11.062042236328125,11.21703815460205,11.084966659545898,11.000564575195312,11.125944137573242,7.740894794464111,11.009302139282227,11.03368854522705],"y":[10.839703559875488,10.186578750610352,12.088871002197266,11.572620391845703,10.504829406738281,11.270042419433594,9.26921272277832,10.038911819458008,11.434706687927246,12.629814147949219,10.871581077575684,12.028068542480469,11.07958698272705,10.428178787231445,11.344042778015137,10.428462028503418,10.490863800048828,11.344935417175293,12.197561264038086,9.566756248474121,9.817669868469238,11.714271545410156,9.960370063781738,12.360904693603516,11.22794246673584,10.894606590270996,10.533679008483887,10.630075454711914,9.87071418762207,9.821185111999512,9.701789855957031,10.042207717895508,9.809471130371094,11.43781566619873,10.407062530517578,10.574695587158203,11.926901817321777,12.11008071899414,11.049091339111328,10.14609432220459,10.430465698242188,11.775084495544434,11.677364349365234,9.301335334777832,10.770838737487793,12.002434730529785,10.31279182434082,11.391910552978516,11.587087631225586,11.656115531921387,11.476985931396484,11.198649406433105,8.82095718383789,11.313366889953613,10.857261657714844,11.509666442871094,11.331183433532715,10.272746086120605,10.65829086303711,8.501448631286621,10.625774383544922,12.26149845123291,9.499472618103027,11.583186149597168,11.289894104003906,11.326577186584473,11.532890319824219,11.105368614196777,11.01874828338623,9.384239196777344,11.984138488769531,10.91139030456543,11.137113571166992,10.589387893676758,10.182755470275879,9.874202728271484,11.294371604919434,10.01098918914795,9.999019622802734,10.675689697265625,10.543596267700195,9.270455360412598,12.035409927368164,11.598392486572266,11.212035179138184,10.543935775756836,12.32702350616455,10.308807373046875,9.472911834716797,11.610387802124023,10.236538887023926,10.37879753112793,11.275368690490723,11.778006553649902,10.561485290527344,11.955370903015137,10.657002449035645,12.045339584350586,11.43898868560791,10.645210266113281,10.878558158874512,10.696368217468262,10.704458236694336,10.679771423339844,10.531181335449219,10.0133695602417,11.43203353881836,9.703680038452148,9.909550666809082,10.693717002868652,10.827871322631836,10.224893569946289,11.45480728149414,11.866963386535645,11.744616508483887,12.504663467407227,10.240961074829102,10.940946578979492,11.098469734191895,10.779125213623047,10.96560287475586,11.282730102539062,10.919716835021973,10.956759452819824,11.393665313720703,10.90475845336914,11.064666748046875,9.908555030822754,11.773627281188965,11.363913536071777,11.369292259216309,10.380696296691895,8.743345260620117,9.939522743225098,11.944669723510742,11.036115646362305,10.62712574005127,11.185225486755371,11.206557273864746,10.050843238830566,10.524185180664062,10.2691011428833,10.258854866027832,10.961446762084961,10.621742248535156,11.220978736877441,11.31548023223877,10.203405380249023,10.4852876663208,10.907896041870117,9.832657814025879,10.488471031188965,10.739477157592773,11.731141090393066,11.168075561523438,10.574892044067383,11.775773048400879,10.11162281036377,11.293416023254395,10.826921463012695,10.837160110473633,10.772971153259277,10.462738037109375,11.83816909790039,10.473282814025879,10.910591125488281,10.396522521972656,11.27634334564209,11.158547401428223,9.919575691223145,10.66947078704834,10.751543045043945,10.147286415100098,10.69190788269043,10.694835662841797,11.091699600219727,11.220097541809082,11.514409065246582,10.856880187988281,10.800125122070312,10.943448066711426,10.741830825805664,10.679606437683105,10.934500694274902,11.489663124084473,11.093504905700684,10.951253890991211,10.59508228302002,10.92122745513916,11.007454872131348,10.430818557739258,11.175667762756348,11.588040351867676,10.883882522583008,10.637737274169922,11.37508773803711,10.310274124145508,10.590265274047852,11.624344825744629,10.90420913696289,11.307595252990723,10.851158142089844,10.442911148071289,10.600739479064941,11.035205841064453,10.590719223022461,10.446906089782715,17.1706485748291,11.1589994430542,10.986806869506836,10.864731788635254,10.806295394897461,10.725379943847656,10.876736640930176,10.656420707702637,11.099913597106934,10.704933166503906,10.5697660446167,10.105047225952148,10.75500202178955,10.636931419372559,11.202589988708496,10.860106468200684,10.799151420593262,10.713971138000488,11.105849266052246,10.867669105529785,11.320473670959473,11.143575668334961,10.949877738952637,9.32813835144043,10.729281425476074,11.243111610412598,10.924150466918945,10.770785331726074,10.970190048217773,9.487630844116211,10.352680206298828,10.792567253112793,10.992082595825195,10.991250038146973,10.314839363098145,10.948410987854004,10.87873363494873,10.77352237701416,10.73262882232666,10.933393478393555,10.832498550415039,10.834753036499023,10.474137306213379],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"#00CC96","size":3},"mode":"markers","name":"cluster 2","x":[-21.09304428100586,-18.89359474182129,-19.406923294067383,-17.72010040283203,-17.608123779296875,-19.196523666381836,-18.72412872314453,-16.56171226501465,-18.312789916992188,-19.164260864257812,-18.526185989379883,-17.9394588470459,-18.133909225463867,-19.553863525390625,-17.998647689819336,-18.76464080810547,-18.749082565307617,-17.27752685546875,-17.42732048034668,-17.758974075317383,-18.442039489746094,-18.77231216430664,-19.320655822753906,-19.9549560546875,-18.55945587158203,-18.567773818969727,-18.347375869750977,-16.82990264892578,-20.67626953125,-19.370582580566406,-17.742374420166016,-18.299108505249023,-18.769290924072266,-20.718910217285156,-18.122543334960938,-18.798185348510742,-18.142642974853516,-17.372394561767578,-17.59496307373047,-19.159996032714844,-19.624631881713867,-17.715282440185547,-17.53016471862793,-18.60016441345215,-17.694026947021484,-17.728857040405273,-18.787425994873047,-18.19661521911621,-19.195695877075195,-19.298927307128906,-18.494298934936523,-18.57719612121582,-17.953712463378906,-17.67292022705078,-19.66877555847168,-19.57184410095215,-18.879972457885742,-19.587005615234375,-18.46196174621582,-19.900075912475586,-20.5544490814209,-18.98872947692871,-19.79622459411621,-19.60041618347168,-19.380680084228516,-18.974096298217773,-18.48822593688965,-16.70694351196289,-17.81269645690918,-19.056983947753906,-19.056087493896484,-17.974769592285156,-19.04264259338379,-19.20612335205078,-18.685165405273438,-20.333818435668945,-21.989877700805664,-18.28467559814453,-19.16360092163086,-18.646310806274414,-16.830665588378906,-20.961109161376953,-18.360748291015625,-17.928024291992188,-19.579891204833984,-19.51454734802246,-18.261838912963867,-18.96518325805664,-18.016895294189453,-18.086570739746094,-19.093307495117188,-17.65562629699707,-18.929523468017578,-21.462553024291992,-19.808687210083008,-18.836393356323242,-17.887144088745117,-18.851856231689453,-18.152788162231445,-19.6751766204834,-18.515289306640625,-19.173559188842773,-18.54190444946289,-19.689653396606445,-18.82146453857422,-18.749671936035156,-17.614185333251953,-17.21860694885254,-18.9287166595459,-17.6899471282959,-18.76860237121582,-18.22214126586914,-21.157909393310547,-18.471590042114258,-17.670778274536133,-18.673521041870117,-18.626354217529297,-19.01644515991211,-18.120332717895508,-19.390623092651367,-19.211639404296875,-18.12376594543457,-18.60129737854004,-18.978979110717773,-18.32505989074707,-18.144397735595703,-19.671586990356445,-20.552244186401367,-19.256765365600586,-18.154090881347656,-18.16156005859375,-18.18482208251953,-18.783172607421875,-20.003801345825195,-18.83969497680664,-18.660633087158203,-18.575536727905273,-18.83479881286621,-17.403369903564453,-18.857839584350586,-18.91476821899414,-18.717294692993164,-18.958101272583008,-19.43239974975586,-18.36954689025879,-18.301010131835938,-18.810277938842773,-18.276369094848633,-18.583539962768555,-19.197229385375977,-18.24941635131836,-18.907445907592773,-18.69437026977539,-18.28068733215332,-18.65855598449707,-18.649723052978516,-18.722867965698242,-19.42467498779297,-18.657503128051758,-17.864280700683594,-18.142173767089844,-18.842918395996094,-19.127979278564453,-19.825735092163086,-19.470605850219727,-19.6085147857666,-18.5509033203125,-18.543394088745117,-18.812694549560547,-18.978134155273438,-19.44837760925293,-18.703187942504883,-18.197172164916992,-18.383262634277344,-19.389442443847656,-18.633543014526367,-18.60352897644043,-18.746540069580078,-18.528820037841797,-18.968830108642578,-18.749977111816406,-18.80989646911621,-18.979347229003906,-18.860326766967773,-18.870140075683594,-19.678314208984375,-18.867694854736328,-18.860267639160156,-18.5687255859375,-17.8518009185791,-18.392702102661133,-18.697303771972656,-18.829044342041016,-18.91153907775879,-18.602869033813477,-18.416051864624023,-18.794614791870117,-18.445533752441406,-18.531126022338867,-19.026718139648438,-19.01780891418457,-18.859926223754883,-18.85822105407715,-18.995119094848633,-18.537757873535156,-18.87272071838379,-19.043054580688477,-17.809518814086914,-17.98634147644043,-19.201221466064453,-18.20384407043457,-17.951045989990234,-18.600614547729492,-18.67701530456543,-18.188356399536133,-18.944454193115234,-18.86894416809082,-18.72344398498535,-18.79364585876465,-18.70955467224121,-18.921138763427734,-18.796295166015625,-19.12570571899414,-18.82134246826172,-18.64803695678711,-18.418094635009766,-19.12483024597168,-18.73208236694336,-18.839662551879883,-18.49126434326172,-18.39255142211914,-18.423479080200195,-19.155466079711914,-18.38325309753418,-18.67487335205078,-18.91825294494629,-18.54463768005371,-18.059532165527344,-18.621013641357422,-18.71620750427246,-18.53838539123535,-18.489078521728516,-18.64266014099121,-18.84544563293457,-18.814746856689453,-18.617530822753906,-18.78776741027832,-18.8233585357666,-18.718942642211914,-18.610231399536133],"y":[-3.9462175369262695,-5.365373611450195,-4.698009967803955,-5.4087958335876465,-6.667239665985107,-4.905521869659424,-4.981022357940674,-5.389160633087158,-7.848189353942871,-4.970628261566162,-5.776336669921875,-6.596185207366943,-6.719605922698975,-5.840273857116699,-5.1966872215271,-5.029383659362793,-6.217555046081543,-4.698990345001221,-5.885217189788818,-6.222939968109131,-5.274539470672607,-6.0197858810424805,-5.174999713897705,-5.250279903411865,-5.392036437988281,-5.914658069610596,-6.15630578994751,-6.149774074554443,-4.406765460968018,-5.400729656219482,-5.577253341674805,-5.253227233886719,-5.310800552368164,-4.095142364501953,-6.75627326965332,-5.3935394287109375,-5.1950483322143555,-6.665519714355469,-6.367669582366943,-4.750723361968994,-4.535514831542969,-5.158735275268555,-6.0139312744140625,-7.187129497528076,-5.587166786193848,-2.4393415451049805,-5.48872184753418,-5.893060684204102,-5.169680118560791,-6.436264991760254,-5.768306255340576,-4.737150192260742,-5.613711357116699,-4.408064365386963,-5.445734024047852,-4.248260021209717,-5.840751647949219,-6.01210880279541,-4.921758651733398,-4.475790977478027,-4.6717448234558105,-4.17664098739624,-5.770675182342529,-5.62941312789917,-5.100161552429199,-6.251237392425537,-5.8424153327941895,-4.756065845489502,-5.306107521057129,-5.464851379394531,-4.208014965057373,-5.63125467300415,-5.0065155029296875,-5.144907474517822,-5.557775497436523,-5.516348838806152,-4.987445831298828,-6.136447906494141,-5.273672103881836,-6.760018348693848,-7.779770374298096,-7.555179595947266,-3.627814769744873,-4.708025932312012,-4.636620998382568,-4.975568771362305,-3.8631861209869385,-5.528895378112793,-5.13922119140625,-6.183318138122559,-5.530783176422119,-5.308929920196533,-5.7004714012146,-6.053252220153809,-5.563735485076904,-6.273633003234863,-6.559990406036377,-4.0843892097473145,-6.772822856903076,-5.496373653411865,-5.387583255767822,-6.265588760375977,-4.08669900894165,-5.049618721008301,-6.185205936431885,-5.5920820236206055,-5.873116493225098,-4.819058418273926,-4.929870128631592,-6.236239910125732,-6.18095588684082,-6.234452247619629,-4.2477312088012695,-5.974016189575195,-6.3717780113220215,-4.679630279541016,-5.288517951965332,-5.216290473937988,-6.161468982696533,-5.047900676727295,-5.275083065032959,-4.746511936187744,-4.969201564788818,-5.402195453643799,-5.335000038146973,-5.854090690612793,-5.654438018798828,-5.041797161102295,-5.270432472229004,-4.851434230804443,-5.712462425231934,-5.775331497192383,-5.606128692626953,-5.117011547088623,-6.293584823608398,-5.356616973876953,-4.941466331481934,-5.949162006378174,-4.714179039001465,-5.234983921051025,-5.850681304931641,-5.5193071365356445,-5.397138595581055,-5.029696464538574,-5.573114395141602,-4.65479850769043,-6.096044063568115,-5.340102672576904,-5.464972972869873,-6.423630714416504,-5.9784255027771,-5.326578140258789,-5.439119338989258,-5.596787452697754,-5.305296897888184,-4.6711106300354,-5.473764896392822,-5.17287015914917,-4.730599403381348,-5.1418657302856445,-5.718680381774902,-5.713038921356201,-4.401334762573242,-6.398741722106934,-3.9634509086608887,-4.452395915985107,-5.568471431732178,-5.589285850524902,-5.219752311706543,-4.912606716156006,-5.502899646759033,-5.81412410736084,-6.076737880706787,-6.293636798858643,-5.116075038909912,-5.719602584838867,-5.090619087219238,-5.60156774520874,-6.04959774017334,-3.7307028770446777,-5.339238166809082,-5.474489212036133,-5.036327362060547,-6.1796650886535645,-5.447934150695801,-4.137929916381836,-6.075428009033203,-6.098238945007324,-5.678464412689209,-4.8243303298950195,-5.1723246574401855,-6.003303050994873,-5.48507022857666,-5.526215553283691,-6.480190277099609,-6.539205551147461,-5.6678924560546875,-5.954273700714111,-5.603193283081055,-5.185120582580566,-5.690211772918701,-5.57891845703125,-5.050783157348633,-5.441473960876465,-5.731297016143799,-5.392122268676758,-5.413181304931641,-5.006068706512451,-6.861274242401123,-5.36255407333374,-6.2831034660339355,-5.84762716293335,-5.815194129943848,-5.372671604156494,-5.311596870422363,-5.742543697357178,-5.650458335876465,-5.792514324188232,-5.372308254241943,-5.450221538543701,-5.706465721130371,-5.205440044403076,-5.230306625366211,-5.312855243682861,-5.513335227966309,-5.639489650726318,-5.335122108459473,-5.745950698852539,-5.5245184898376465,-5.391866207122803,-5.904212474822998,-5.728081226348877,-4.852088451385498,-5.444051265716553,-5.537744522094727,-5.369645595550537,-5.269660949707031,-5.213024139404297,-5.487154006958008,-4.963733196258545,-5.531641960144043,-5.7254557609558105,-5.65606689453125,-5.481717586517334,-5.312532424926758,-5.56707763671875,-5.488705158233643,-5.357557773590088,-5.7238054275512695,-5.418074607849121],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"#AB63FA","size":3},"mode":"markers","name":"cluster 3","x":[-19.731082916259766,-22.38245964050293,-19.789838790893555,-19.683073043823242,-19.74149513244629,-19.675376892089844,-20.366039276123047,-21.17650604248047,-20.592819213867188,-19.832876205444336,-20.535539627075195,-21.04725456237793,-21.08646011352539,-20.559391021728516,-19.864805221557617,-20.096866607666016,-20.921600341796875,-19.674131393432617,-19.18958854675293,-20.692596435546875,-19.979618072509766,-21.066997528076172,-22.100189208984375,-21.997873306274414,-21.03421974182129,-20.001432418823242,-19.961034774780273,-21.753202438354492,-21.268415451049805,-21.618114471435547,-18.802940368652344,-20.077133178710938,-21.004079818725586,-21.624454498291016,-20.085052490234375,-21.00869369506836,-21.049442291259766,-21.397920608520508,-18.85047149658203,-21.86111068725586,-21.2210693359375,-21.176755905151367,-21.195297241210938,-20.88426399230957,-20.058216094970703,-20.22893714904785,-20.46788215637207,-20.205896377563477,-19.816471099853516,-20.500337600708008,-20.30000877380371,-21.451763153076172,-19.48648452758789,-20.963388442993164,-21.808746337890625,-20.532087326049805,-20.80862045288086,-21.596349716186523,-21.115619659423828,-19.97161293029785,-20.96674156188965,-20.73948860168457,-22.106048583984375,-21.088409423828125,-21.230060577392578,-20.48041343688965,-20.321739196777344,-21.472200393676758,-21.41373634338379,-21.064416885375977,-19.575275421142578,-20.822986602783203,-19.21134376525879,-20.412229537963867,-21.320608139038086,-20.435728073120117,-22.00689125061035,-20.22583770751953,-20.74637222290039,-20.488994598388672,-20.623746871948242,-20.702301025390625,-19.801729202270508,-20.238113403320312,-20.202194213867188,-19.774267196655273,-21.165733337402344,-22.05877113342285,-22.477970123291016,-21.338735580444336,-19.479013442993164,-20.095603942871094,-21.16917610168457,-20.405717849731445,-20.602313995361328,-20.543054580688477,-20.764469146728516,-21.301387786865234,-21.123981475830078,-21.450740814208984,-20.75960350036621,-20.844829559326172,-19.8469181060791,-19.926132202148438,-20.810720443725586,-19.961029052734375,-20.24656867980957,-21.183332443237305,-20.614614486694336,-20.604440689086914,-20.75160789489746,-18.765493392944336,-20.492979049682617,-21.120288848876953,-20.62491798400879,-20.718097686767578,-21.40839195251465,-20.730989456176758,-20.364768981933594,-20.830127716064453,-20.477155685424805,-20.392818450927734,-20.12152862548828,-19.792428970336914,-21.03192710876465,-20.459413528442383,-19.98517417907715,-20.95758628845215,-21.06414222717285,-20.02515983581543,-20.3040714263916,-20.328922271728516,-21.269222259521484,-20.32646369934082,-21.64946937561035,-20.309467315673828,-21.282493591308594,-20.633127212524414,-20.423585891723633,-20.572891235351562,-20.760005950927734,-20.989643096923828,-20.22769546508789,-20.56608772277832,-19.971647262573242,-19.406879425048828,-20.411863327026367,-20.60555076599121,-20.956680297851562,-20.388235092163086,-19.017505645751953,-20.506145477294922,-20.3170108795166,-21.14582061767578,-20.77361297607422,-19.794490814208984,-21.004409790039062,-20.698843002319336,-20.475818634033203,-20.47801399230957,-20.141456604003906,-21.215120315551758,-20.777963638305664,-20.719802856445312,-19.80467414855957,-19.96698570251465,-20.77224349975586,-20.536876678466797,-20.62819480895996,-20.387353897094727,-19.92801856994629,-19.849042892456055,-20.59773826599121,-20.58018684387207,-20.672107696533203,-20.406442642211914,-20.28687858581543,-20.16901206970215,-21.39153289794922,-20.60000991821289,-20.336374282836914,-20.455677032470703,-20.390304565429688,-20.75653648376465,-20.717220306396484,-20.687744140625,-20.826465606689453,-20.72105598449707,-20.666786193847656,-20.704130172729492,-20.710485458374023,-20.5435848236084,-20.198575973510742,-20.362884521484375,-20.34478187561035,-20.63017463684082,-20.880491256713867,-19.84199333190918,-20.83553123474121,-20.40234375,-20.558467864990234,-20.343921661376953,-20.69133186340332,-20.711841583251953,-20.685388565063477,-20.67680549621582,-20.50754165649414,-20.523107528686523,-20.637577056884766,-20.490556716918945,-20.57921600341797,-20.744033813476562,-20.560348510742188,-20.436569213867188,-20.7112979888916,-20.831663131713867,-20.764636993408203,-20.64147186279297,-20.525894165039062,-20.596277236938477,-20.27511215209961,-20.51163673400879,-20.694475173950195,-21.466848373413086,-20.63806915283203,-20.739145278930664,-20.664907455444336,-20.72491455078125,-20.8062801361084,-20.57762908935547,-20.809932708740234,-20.333662033081055,-20.885297775268555,-20.308382034301758,-20.54722785949707,-20.591360092163086,-20.52828598022461,-20.639307022094727,-20.778064727783203,-20.542238235473633,-20.51249122619629,-20.694673538208008,-20.779468536376953,-20.629486083984375,-20.527889251708984,-20.819477081298828,-20.629863739013672,-20.456083297729492,-20.614286422729492,-20.75467872619629],"y":[7.226347923278809,8.104235649108887,9.033217430114746,8.619539260864258,10.316058158874512,7.357335090637207,10.236699104309082,8.87075138092041,9.26149845123291,9.665105819702148,9.729555130004883,9.440858840942383,7.44549560546875,8.755596160888672,8.775742530822754,7.837094783782959,6.805335521697998,8.007126808166504,9.069034576416016,8.833173751831055,8.978630065917969,8.196060180664062,8.103081703186035,10.500894546508789,7.369081497192383,8.570425987243652,9.648719787597656,8.903018951416016,9.204081535339355,7.612142086029053,7.631712436676025,8.407816886901855,9.105984687805176,10.30273723602295,10.66319465637207,8.657126426696777,9.46812629699707,10.130621910095215,8.641464233398438,7.595956325531006,9.295832633972168,8.378538131713867,8.745247840881348,9.622722625732422,9.176819801330566,9.165411949157715,10.17850399017334,8.742300033569336,9.29708194732666,9.515795707702637,9.496200561523438,9.855558395385742,10.273195266723633,8.791254043579102,10.121352195739746,9.465758323669434,9.563578605651855,9.3624267578125,8.044997215270996,8.369465827941895,9.018966674804688,9.092660903930664,10.69743537902832,8.241719245910645,10.16899299621582,10.053014755249023,8.90282917022705,8.850278854370117,9.264252662658691,7.216431617736816,8.228232383728027,9.61838436126709,9.213205337524414,9.141987800598145,8.73296070098877,9.260125160217285,10.168309211730957,9.247827529907227,9.517373085021973,9.486605644226074,9.989277839660645,9.985631942749023,10.070286750793457,8.352104187011719,8.59418773651123,10.661940574645996,8.820965766906738,9.94298267364502,7.541391372680664,8.202345848083496,9.594078063964844,10.041165351867676,9.363113403320312,9.001022338867188,8.911073684692383,9.86727237701416,9.57371711730957,9.146712303161621,9.256174087524414,8.286968231201172,8.50069808959961,9.597248077392578,9.032942771911621,9.183785438537598,9.542243957519531,9.032093048095703,8.375314712524414,10.6718111038208,9.118300437927246,8.144512176513672,8.733291625976562,7.677799701690674,9.147794723510742,8.92497444152832,8.861501693725586,9.725566864013672,10.06501293182373,9.733532905578613,8.722537994384766,8.937151908874512,7.594668388366699,9.293803215026855,10.81201171875,9.40477466583252,9.136399269104004,9.836723327636719,8.057657241821289,9.444192886352539,9.065499305725098,8.58248519897461,9.634801864624023,8.650278091430664,6.744237422943115,7.967889785766602,10.09990406036377,10.385737419128418,9.638261795043945,9.15112018585205,8.950498580932617,8.676064491271973,9.27053165435791,9.112385749816895,9.518973350524902,9.7963228225708,7.978214740753174,9.233514785766602,9.50391960144043,8.115123748779297,9.607251167297363,8.909035682678223,9.564841270446777,9.170310020446777,8.286345481872559,9.708307266235352,9.19487190246582,9.571429252624512,9.064620971679688,9.192028999328613,9.515613555908203,8.691017150878906,9.392646789550781,9.95113754272461,9.655826568603516,9.638477325439453,7.51640510559082,8.519182205200195,8.151068687438965,9.423710823059082,9.126202583312988,10.218196868896484,8.587886810302734,9.189803123474121,8.997472763061523,9.408788681030273,9.411267280578613,9.003954887390137,9.068803787231445,8.57654094696045,8.376411437988281,9.528251647949219,8.35820198059082,9.478812217712402,8.797242164611816,9.614171028137207,9.733089447021484,9.001914024353027,9.173797607421875,8.723958969116211,8.869477272033691,8.975625038146973,9.414525032043457,9.279623985290527,8.496407508850098,9.249917984008789,9.063138961791992,9.679549217224121,8.813994407653809,8.859631538391113,9.519790649414062,8.883431434631348,9.174912452697754,9.009246826171875,9.228202819824219,8.910329818725586,9.408000946044922,8.801340103149414,8.898140907287598,9.389059066772461,8.950972557067871,8.597966194152832,8.563261032104492,9.343417167663574,9.270484924316406,9.115826606750488,8.507081031799316,9.367959976196289,9.266206741333008,9.049388885498047,9.116264343261719,9.200115203857422,8.93225383758545,8.923412322998047,8.85167121887207,8.784868240356445,9.191920280456543,9.33290958404541,9.253369331359863,8.881270408630371,9.102346420288086,9.193692207336426,8.802395820617676,9.191869735717773,8.88604736328125,8.971256256103516,8.956252098083496,8.893634796142578,9.103275299072266,9.151788711547852,9.27951717376709,9.156179428100586,9.167258262634277,8.868560791015625,9.240450859069824,9.10138988494873,9.154092788696289,9.017655372619629,9.595831871032715,9.112775802612305,9.138504981994629,8.703923225402832],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"#FFA15A","size":3},"mode":"markers","name":"cluster 4","x":[-9.175100326538086,-10.716907501220703,-10.726874351501465,-9.815886497497559,-9.400250434875488,-10.62441349029541,-7.344122409820557,-9.54061222076416,-10.116421699523926,-8.301437377929688,-11.397050857543945,-8.975103378295898,-10.076102256774902,-9.324216842651367,-9.985421180725098,-10.750006675720215,-8.627120018005371,-10.777556419372559,-11.10435962677002,-9.095454216003418,-10.007133483886719,-10.067122459411621,-9.367341041564941,-10.208551406860352,-9.062188148498535,-10.099392890930176,-11.50991153717041,-12.310323715209961,-9.73578929901123,-8.783028602600098,-7.7662458419799805,-9.940951347351074,-9.10755443572998,-9.453938484191895,-9.344366073608398,-10.368194580078125,-8.761310577392578,-10.37009334564209,-8.494026184082031,-7.931295871734619,-9.432374954223633,-9.199310302734375,-9.249691009521484,-10.741416931152344,-6.975325584411621,-10.181041717529297,-9.186158180236816,-9.125078201293945,-9.966309547424316,-10.896998405456543,-9.926901817321777,-8.77364444732666,-11.032240867614746,-10.546788215637207,-9.178365707397461,-9.000394821166992,-10.037184715270996,-9.1764554977417,-9.406737327575684,-9.083206176757812,-10.917478561401367,-9.886030197143555,-9.920478820800781,-10.46277141571045,-9.785969734191895,-9.214327812194824,-10.619718551635742,-10.524287223815918,-8.867352485656738,-8.840475082397461,-9.673160552978516,-9.955704689025879,-9.03779411315918,-9.119434356689453,-8.322237968444824,-9.366148948669434,-9.719332695007324,-10.583232879638672,-13.029067993164062,-9.35619831085205,-9.234796524047852,-9.609435081481934,-9.220083236694336,-9.26039981842041,-9.712023735046387,-11.550233840942383,-12.41116714477539,-9.396222114562988,-10.41490364074707,-9.366673469543457,-9.511944770812988,-10.430280685424805,-9.927976608276367,-10.242878913879395,-9.6993989944458,-9.116860389709473,-8.766212463378906,-9.140471458435059,-8.851835250854492,-9.544793128967285,-10.018913269042969,-10.519174575805664,-9.625988006591797,-8.505095481872559,-9.855740547180176,-9.025830268859863,-8.284582138061523,-9.05695915222168,-9.135666847229004,-9.563314437866211,-10.735196113586426,-9.237994194030762,-8.629672050476074,-10.032825469970703,-9.254179954528809,-9.54594898223877,-9.08013916015625,-10.205679893493652,-10.05886173248291,-10.071508407592773,-9.798309326171875,-9.809744834899902,-9.3975191116333,-9.490707397460938,-10.13472843170166,-9.934943199157715,-9.747115135192871,-9.910721778869629,-9.540874481201172,-9.56183910369873,-10.610647201538086,-9.106080055236816,-10.239164352416992,-9.618350982666016,-10.120057106018066,-9.479246139526367,-9.410802841186523,-9.344642639160156,-10.603217124938965,-9.857659339904785,-9.651808738708496,-9.790458679199219,-9.613485336303711,-8.753429412841797,-9.814496994018555,-10.036874771118164,-9.087752342224121,-10.086953163146973,-10.012587547302246,-9.581509590148926,-8.895777702331543,-9.217394828796387,-9.527303695678711,-9.137199401855469,-9.382330894470215,-8.648263931274414,-9.50781536102295,-9.926426887512207,-9.635238647460938,-8.721921920776367,-9.50088882446289,-9.291630744934082,-9.131155014038086,-9.215456008911133,-10.339070320129395,-10.079187393188477,-9.27904224395752,-9.018728256225586,-10.05575942993164,-10.040545463562012,-9.470974922180176,-9.823139190673828,-9.890298843383789,-9.765120506286621,-9.348893165588379,-9.688057899475098,-8.818222999572754,-8.987919807434082,-9.901732444763184,-9.591936111450195,-9.50507640838623,-9.660930633544922,-9.68260383605957,-9.728524208068848,-10.285073280334473,-9.63068962097168,-9.512048721313477,-10.065714836120605,-9.741775512695312,-9.478682518005371,-9.732453346252441,-9.622611045837402,-9.342430114746094,-9.70829963684082,-9.499640464782715,-9.671965599060059,-9.004505157470703,-9.380928993225098,-10.186408042907715,-9.355117797851562,-9.316676139831543,-9.157170295715332,-9.442183494567871,-9.637862205505371,-9.401167869567871,-9.710651397705078,-9.362649917602539,-9.573434829711914,-9.921152114868164,-10.042287826538086,-9.849603652954102,-9.761045455932617,-9.615523338317871,-9.695103645324707,-9.586164474487305,-9.896744728088379,-9.528752326965332,-9.726773262023926,-9.816180229187012,-9.5851411819458,-9.38146686553955,-9.749384880065918,-9.657855987548828,-9.518509864807129,-9.74229621887207,-9.72342586517334,-9.71842098236084,-9.483772277832031,-9.797788619995117,-9.688323974609375,-9.538456916809082,-9.60282039642334,-9.856755256652832,-9.03917121887207,-9.582382202148438,-9.78902530670166,-9.568499565124512,-9.978431701660156,-9.486825942993164,-9.960480690002441,-9.95223331451416,-9.556676864624023,-9.660000801086426,-9.885618209838867,-9.766162872314453,-9.544059753417969,-9.680782318115234,-9.638301849365234,-9.543113708496094,-9.835493087768555],"y":[23.71005630493164,24.434946060180664,24.7990665435791,25.16131591796875,23.18424415588379,25.865015029907227,23.700353622436523,24.260761260986328,25.27256965637207,25.488924026489258,25.38631248474121,24.6440372467041,23.544292449951172,24.583459854125977,24.50491714477539,24.193857192993164,26.018604278564453,24.958282470703125,22.140544891357422,25.143495559692383,24.255949020385742,24.985139846801758,24.62743377685547,24.735111236572266,25.36219024658203,24.87854766845703,24.236425399780273,24.644018173217773,25.20848846435547,23.361310958862305,26.687362670898438,24.555564880371094,24.602924346923828,24.475061416625977,23.210617065429688,25.330406188964844,24.719011306762695,24.235200881958008,23.11083221435547,25.520292282104492,23.07254409790039,22.955169677734375,25.003313064575195,24.363290786743164,24.05109214782715,24.255617141723633,26.04904556274414,23.772348403930664,23.859418869018555,25.401287078857422,24.5909423828125,25.852848052978516,22.828916549682617,24.948514938354492,24.992891311645508,22.929244995117188,25.512107849121094,23.80311393737793,24.839462280273438,25.699600219726562,24.464555740356445,25.499780654907227,24.68043327331543,24.882686614990234,23.810190200805664,24.140758514404297,25.39373016357422,24.347410202026367,23.202136993408203,24.59684944152832,25.90167808532715,25.97957992553711,24.573381423950195,25.441829681396484,22.616294860839844,23.014955520629883,24.44513511657715,23.308753967285156,23.606128692626953,24.05533790588379,26.398555755615234,24.89359474182129,24.533802032470703,23.951757431030273,24.03046417236328,23.929216384887695,23.567264556884766,25.64837646484375,22.922143936157227,23.52313804626465,25.096357345581055,25.30131721496582,24.090757369995117,25.066368103027344,24.553146362304688,25.137805938720703,23.910133361816406,24.781591415405273,23.84627342224121,24.872146606445312,25.397186279296875,24.57590103149414,24.203405380249023,23.892047882080078,24.9432373046875,22.331579208374023,23.626291275024414,24.326519012451172,24.60196304321289,24.273866653442383,24.28462028503418,24.876590728759766,24.693378448486328,24.37127685546875,24.944883346557617,24.648347854614258,23.664215087890625,24.59265899658203,22.996437072753906,24.077856063842773,24.72673988342285,23.809951782226562,24.9081974029541,24.9793758392334,24.970949172973633,24.284648895263672,24.2022762298584,23.795297622680664,22.956127166748047,23.945980072021484,23.901756286621094,24.955827713012695,24.566171646118164,23.570802688598633,25.16583251953125,24.882144927978516,24.69062042236328,24.271867752075195,23.925127029418945,24.469219207763672,24.466550827026367,24.942550659179688,24.178647994995117,24.26386070251465,24.602840423583984,23.36650848388672,25.246816635131836,25.26300621032715,24.687702178955078,26.56385612487793,25.162532806396484,24.6497859954834,23.867633819580078,25.09109115600586,25.197996139526367,24.6021785736084,25.678621292114258,24.3225040435791,24.67591094970703,27.065052032470703,24.59858512878418,23.705337524414062,24.22926139831543,25.086965560913086,24.69145965576172,24.300960540771484,24.198423385620117,24.285240173339844,24.340286254882812,24.9720401763916,24.561065673828125,24.67360496520996,24.49479866027832,24.543243408203125,24.612186431884766,24.580936431884766,24.241348266601562,25.481952667236328,24.409841537475586,24.89671516418457,24.61168098449707,23.794567108154297,25.636043548583984,24.808198928833008,24.5532283782959,25.59581184387207,24.712881088256836,24.81939125061035,24.68113899230957,24.427391052246094,24.679073333740234,24.730823516845703,24.060043334960938,25.1190242767334,24.605194091796875,24.735774993896484,24.477445602416992,25.033262252807617,24.775474548339844,24.8116512298584,24.065353393554688,24.753053665161133,24.515722274780273,24.385791778564453,24.820634841918945,24.635459899902344,24.335969924926758,24.22386932373047,24.522226333618164,24.351804733276367,23.74639320373535,24.62469482421875,24.571989059448242,24.232967376708984,24.353113174438477,24.0767765045166,24.219167709350586,24.660064697265625,24.597347259521484,24.306533813476562,24.382244110107422,24.363121032714844,24.340511322021484,24.71736717224121,24.296337127685547,24.423919677734375,23.8426570892334,24.50372886657715,24.41991424560547,24.547208786010742,24.302461624145508,24.126386642456055,24.574922561645508,24.362939834594727,24.6966609954834,24.598400115966797,24.416542053222656,24.493196487426758,24.693058013916016,24.65599822998047,24.27741050720215,24.430294036865234,24.615015029907227,24.422578811645508,24.249420166015625,24.414793014526367,24.298206329345703,24.337114334106445,24.375808715820312,24.31322479248047],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"#19D3F3","size":3},"mode":"markers","name":"cluster 5","x":[24.910682678222656,25.348167419433594,25.48988151550293,25.407487869262695,25.732444763183594,23.847015380859375,22.813661575317383,23.38425636291504,25.381792068481445,25.977720260620117,23.921180725097656,25.459186553955078,25.44654655456543,23.869754791259766,23.65787696838379,24.63576316833496,24.070219039916992,24.41889762878418,26.159875869750977,23.499589920043945,23.049659729003906,24.817663192749023,26.21938705444336,26.0670108795166,26.25128173828125,26.47380828857422,24.570749282836914,23.519840240478516,24.205509185791016,23.855426788330078,24.962203979492188,23.670520782470703,25.89510154724121,25.836151123046875,25.047039031982422,24.668333053588867,25.35805892944336,23.431467056274414,24.889062881469727,24.470182418823242,25.644718170166016,24.241649627685547,25.642086029052734,24.739887237548828,26.86212730407715,26.087919235229492,24.986738204956055,24.29734992980957,25.399991989135742,25.015504837036133,25.877485275268555,24.436172485351562,23.89093589782715,24.6669864654541,25.35089111328125,25.90843963623047,25.37848472595215,24.64467430114746,22.98560333251953,23.284969329833984,24.967267990112305,24.69975471496582,23.997577667236328,26.68948745727539,24.033126831054688,24.847068786621094,24.163692474365234,25.16253662109375,25.43760108947754,25.578535079956055,24.522985458374023,24.069684982299805,24.80597686767578,25.665630340576172,25.82100486755371,26.08856964111328,24.920940399169922,24.668107986450195,24.812049865722656,24.51218032836914,23.88321304321289,26.501018524169922,26.270427703857422,24.104711532592773,25.693885803222656,25.181488037109375,24.676055908203125,24.59322166442871,24.386714935302734,25.93047332763672,25.701984405517578,24.26602554321289,24.1798038482666,24.381935119628906,24.643356323242188,23.678293228149414,23.199356079101562,23.61591148376465,24.427433013916016,24.917470932006836,24.892045974731445,23.972444534301758,26.088579177856445,24.547359466552734,24.9840030670166,24.180889129638672,24.984189987182617,25.684551239013672,24.167797088623047,24.696142196655273,25.695602416992188,25.066173553466797,25.667423248291016,25.642000198364258,25.22545051574707,24.998003005981445,25.02340316772461,23.623432159423828,24.290231704711914,23.941911697387695,24.080957412719727,24.83702850341797,25.142223358154297,25.341718673706055,24.901973724365234,24.798099517822266,24.78040885925293,25.274559020996094,25.017114639282227,25.29698944091797,25.75497055053711,24.743593215942383,24.934101104736328,22.918476104736328,23.8627986907959,25.041152954101562,24.40079689025879,25.08211326599121,25.03680419921875,25.251964569091797,26.824872970581055,25.268795013427734,25.38536834716797,24.15636444091797,25.148794174194336,26.042984008789062,25.058656692504883,24.967531204223633,25.504398345947266,26.26141929626465,25.03709602355957,25.296966552734375,24.482267379760742,25.098953247070312,25.136871337890625,25.20359992980957,24.501789093017578,25.006486892700195,25.160280227661133,24.87706756591797,25.356412887573242,24.84685707092285,24.532569885253906,25.408498764038086,24.9771728515625,23.786928176879883,25.272716522216797,25.086551666259766,25.314998626708984,25.574298858642578,24.647024154663086,24.610776901245117,25.17986297607422,24.30775260925293,24.306135177612305,24.84845733642578,23.967309951782227,25.250280380249023,25.262104034423828,25.268165588378906,24.376819610595703,24.788846969604492,24.808883666992188,25.938684463500977,24.916746139526367,25.148916244506836,24.283063888549805,23.665111541748047,25.89096450805664,24.367918014526367,24.964149475097656,25.167160034179688,25.62744140625,24.95513153076172,24.773771286010742,25.032804489135742,25.15969467163086,22.504192352294922,24.33920669555664,24.548091888427734,25.127111434936523,25.07375717163086,24.864395141601562,24.53053092956543,24.667316436767578,24.535911560058594,24.702308654785156,25.148649215698242,24.254562377929688,24.9354190826416,23.8061580657959,24.985576629638672,24.732053756713867,24.903745651245117,25.011648178100586,24.93807029724121,25.720577239990234,24.046890258789062,24.719242095947266,24.302921295166016,25.196651458740234,25.012319564819336,25.0021915435791,24.866127014160156,25.13617706298828,24.783721923828125,26.20484161376953,24.779682159423828,25.24911117553711,25.198650360107422,24.801115036010742,25.046154022216797,24.449413299560547,24.317089080810547,24.401512145996094,25.125856399536133,26.171432495117188,24.532241821289062,24.47679901123047,25.24970817565918,24.755048751831055,24.753826141357422,24.841386795043945,25.167728424072266,24.661977767944336,25.060508728027344,24.429502487182617,24.954256057739258,23.826745986938477,24.808055877685547],"y":[3.330777645111084,6.019943714141846,4.861457347869873,2.84415340423584,3.5437655448913574,3.534959554672241,3.854865789413452,3.6172451972961426,3.4784069061279297,3.49247145652771,4.2546916007995605,3.9742183685302734,3.6750690937042236,3.236593008041382,6.464629173278809,4.957302570343018,3.328254222869873,3.1449062824249268,3.6362767219543457,3.9830832481384277,3.4315762519836426,2.0553534030914307,3.0896413326263428,4.786179065704346,2.4708950519561768,1.6898365020751953,2.7561004161834717,4.422569751739502,5.312889099121094,2.843686103820801,3.898256778717041,3.3802926540374756,3.081857919692993,2.549006700515747,6.568864822387695,1.8561350107192993,3.5219953060150146,4.028653621673584,4.867859840393066,3.298518419265747,2.912851572036743,2.8183648586273193,3.6120944023132324,3.2770588397979736,4.81455135345459,3.034832715988159,3.2831168174743652,3.4007396697998047,3.924490451812744,4.370161533355713,2.5357303619384766,3.819746255874634,4.093968391418457,4.128928184509277,3.7001116275787354,4.042128086090088,3.876143217086792,3.081054925918579,3.8087897300720215,3.9353036880493164,5.900588035583496,4.562702655792236,5.09755802154541,4.889177322387695,3.416018009185791,3.6303422451019287,2.641890048980713,2.152134418487549,3.349952220916748,2.3222546577453613,2.6651864051818848,4.539223670959473,4.1497297286987305,1.6451940536499023,2.82637357711792,2.9408631324768066,3.226947784423828,3.803784132003784,2.7109568119049072,3.7321364879608154,2.609877347946167,4.616680145263672,3.7110846042633057,3.902168035507202,3.286947250366211,2.775019645690918,2.888932704925537,4.100666046142578,3.6565377712249756,5.0195817947387695,3.8004181385040283,3.8139235973358154,3.004836320877075,4.7677717208862305,3.8818089962005615,3.8270537853240967,3.622887372970581,2.692537784576416,3.8510825634002686,3.7565150260925293,3.519717216491699,3.420626401901245,3.970449209213257,3.4709067344665527,3.741607666015625,4.763010025024414,2.6735899448394775,3.513038396835327,4.614933013916016,2.8562445640563965,2.980661392211914,2.744201898574829,4.365338325500488,4.760097503662109,3.569880485534668,4.1554412841796875,3.5923776626586914,4.546722412109375,3.211880683898926,3.9002840518951416,3.9789390563964844,3.5970873832702637,4.157991886138916,3.7178680896759033,3.418029546737671,3.920177936553955,4.259256362915039,3.2298507690429688,3.52191162109375,2.1080965995788574,4.146679401397705,3.8270671367645264,3.7885706424713135,4.3934712409973145,3.771980047225952,2.152224063873291,4.0874176025390625,3.792588472366333,3.299318790435791,2.886904239654541,4.443240165710449,3.076115608215332,2.786410093307495,4.446681976318359,3.3221421241760254,4.015493392944336,3.7783203125,4.631606578826904,3.8057150840759277,4.460583686828613,3.4362952709198,3.932455539703369,3.518686532974243,3.353119134902954,3.7304670810699463,3.748790979385376,3.7513513565063477,3.358006000518799,3.458204507827759,3.7707579135894775,3.6961021423339844,3.5182719230651855,2.735109329223633,3.5971291065216064,3.432581663131714,4.07050895690918,4.29788875579834,2.949314832687378,3.626476764678955,3.2394449710845947,3.838649272918701,3.7654170989990234,3.8896117210388184,3.830101490020752,4.4514851570129395,3.5939559936523438,3.9622817039489746,3.3246803283691406,3.969759702682495,3.900968074798584,4.015563488006592,3.4784393310546875,3.356776237487793,4.089617729187012,3.585742473602295,3.5050313472747803,3.545259714126587,7.427239418029785,3.277217388153076,3.6106390953063965,3.5076332092285156,3.693650722503662,4.113780975341797,4.582255840301514,3.250608205795288,3.2966461181640625,3.6085402965545654,4.6655964851379395,4.20128870010376,3.6117734909057617,3.3306725025177,3.6887853145599365,3.5095701217651367,3.677093267440796,3.716674566268921,3.943042755126953,3.4887824058532715,3.740898847579956,3.957815408706665,3.2310473918914795,4.098201274871826,3.6408519744873047,3.6249303817749023,3.524247646331787,3.3207461833953857,3.4133565425872803,4.97858190536499,4.026023864746094,3.5367562770843506,4.091683864593506,3.728238105773926,3.69111704826355,3.712973117828369,3.7348504066467285,3.814938545227051,3.5878329277038574,4.956797122955322,3.7523672580718994,4.050398349761963,3.9145822525024414,3.5911078453063965,3.399374485015869,3.8401505947113037,3.9698643684387207,3.6713316440582275,4.1900482177734375,4.435842990875244,4.2473626136779785,3.996246814727783,3.4805426597595215,3.6318531036376953,3.868190288543701,3.6766669750213623,3.653940200805664,3.8563899993896484,3.699369430541992,3.8119192123413086,3.957099676132202,3.7662651538848877,4.227260112762451],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"}]},{"data":[{"marker":{"color":"#636EFA","size":3},"mode":"markers","name":"cluster 0","x":[2.498114585876465,2.601865768432617,2.538365125656128,2.5138742923736572,2.5985476970672607,2.4814088344573975,2.587120294570923,2.560072898864746,2.4582483768463135,2.6406636238098145,2.5568783283233643,2.5950706005096436,2.5352401733398438,2.4481043815612793,2.4442193508148193,2.4952213764190674,2.556384325027466,2.5708465576171875,2.5983312129974365,2.5230584144592285,2.495473861694336,2.624905824661255,2.549787998199463,2.57858943939209,2.55234694480896,2.559286594390869,2.408773422241211,2.5523102283477783,2.618621587753296,2.548177719116211,2.5978548526763916,2.545949697494507,2.564082145690918,2.541621446609497,2.5201430320739746,2.54762864112854,2.535665512084961,2.583848237991333,2.543654441833496,2.5375587940216064,2.4992153644561768,2.5960192680358887,2.576669931411743,2.6289560794830322,2.564706325531006,2.596384048461914,2.5521442890167236,2.5908801555633545,2.560925245285034,2.6047515869140625,2.577768564224243,2.564037561416626,2.588871955871582,2.5408999919891357,2.5897066593170166,2.588230848312378,2.5482029914855957,2.592527151107788,2.5643203258514404,2.5932586193084717,2.558424949645996,2.552420139312744,2.5750505924224854,2.592972993850708,2.595883846282959,2.594163417816162,2.5770318508148193,2.5308709144592285,2.6171934604644775,2.5782368183135986,2.5874743461608887,2.568121910095215,2.59187388420105,2.6064510345458984,2.620163679122925,2.5917322635650635,2.5773675441741943,2.570368528366089,2.587996244430542,2.5681397914886475,2.5867292881011963,2.57531476020813,2.596486806869507,2.574284076690674,2.5614335536956787,2.564682722091675,2.5653982162475586,2.5923333168029785,2.568755626678467,2.589128255844116,2.5837242603302,2.582557439804077,2.5789244174957275,2.5910637378692627,2.531266450881958,2.561631917953491,2.572819709777832,2.5637760162353516,2.5932693481445312,2.5608086585998535,2.5474131107330322,2.5959055423736572,2.5938193798065186,2.5844972133636475,2.587862491607666,2.57401704788208,2.5723817348480225,2.588559627532959,2.573969602584839,2.5849173069000244,2.587053060531616,2.6026077270507812,2.5918822288513184,2.5959701538085938,2.5830881595611572,2.5860865116119385,2.573258638381958,2.58516001701355,2.5840303897857666,2.5877137184143066,2.584113597869873,2.5871174335479736,2.5898005962371826,2.597860813140869,2.5950334072113037,2.587939500808716,2.5953361988067627,2.590273141860962,2.5887439250946045,2.586682081222534,2.616645097732544,2.5935957431793213,2.5784761905670166,2.590280055999756,2.5923123359680176,2.595954656600952,2.5913898944854736,2.5913262367248535,2.5930731296539307,2.6072311401367188,2.580484628677368,2.5896401405334473,2.5893778800964355,2.590762138366699,2.583742380142212,2.586103677749634,2.5885815620422363,2.5838401317596436,2.596693754196167,2.5885472297668457,2.5816633701324463,2.587524175643921,2.5830233097076416,2.5817723274230957,2.5836331844329834,2.5824551582336426,2.578352451324463,2.5722014904022217,2.579080104827881,2.5700972080230713,2.5736074447631836,2.582742691040039,2.5857315063476562,2.579340934753418,2.5847063064575195,2.5787904262542725,2.5870792865753174,2.5873124599456787,2.5856781005859375,2.5859663486480713,2.591655969619751,2.5817148685455322,2.5836548805236816,2.579257011413574,2.592663288116455,2.586966037750244,2.5779693126678467,2.575671434402466,2.574436902999878,2.5787341594696045,2.5745983123779297,2.575995445251465,2.573795795440674,2.576875686645508,2.578341245651245,2.581613063812256,2.5722997188568115,2.57411527633667,2.580104112625122,2.5779919624328613,2.5819554328918457,2.575012683868408,2.5783443450927734,2.5781993865966797,2.5742053985595703,2.5771944522857666,2.582606792449951,2.577592611312866,2.5802981853485107,2.5777785778045654,2.5766756534576416,2.5782856941223145,2.598837375640869,2.579425811767578,2.579803705215454,2.5791332721710205,2.5823020935058594,2.580625295639038,2.5793516635894775,2.5806286334991455,2.577906847000122,2.5778419971466064,2.575871229171753,2.5763509273529053,2.577014207839966,2.5766637325286865,2.575582981109619,2.5768022537231445,2.571916103363037,2.5749125480651855,2.5750951766967773,2.5779144763946533,2.576200485229492,2.57741641998291,2.577533483505249,2.5781631469726562,2.577686309814453,2.5772314071655273,2.574361562728882,2.573824644088745,2.573593854904175,2.571728467941284,2.572336196899414,2.572031021118164,2.572955846786499,2.5714118480682373,2.5711405277252197,2.57114577293396,2.570823907852173,2.571248769760132,2.569875955581665,2.571899652481079,2.5737154483795166,2.5734174251556396,2.5726964473724365,2.572598457336426,2.5714128017425537,2.5714516639709473,2.5721068382263184,2.5732524394989014],"y":[-21.170204162597656,-21.24049949645996,-21.173612594604492,-21.21587371826172,-21.20311737060547,-21.19548225402832,-21.14067840576172,-21.142717361450195,-21.194869995117188,-21.2011775970459,-21.158044815063477,-21.213563919067383,-21.192123413085938,-21.19369125366211,-21.157861709594727,-21.228561401367188,-21.18321418762207,-21.093101501464844,-21.20949935913086,-21.20182991027832,-21.142776489257812,-21.220821380615234,-21.19171905517578,-21.176984786987305,-21.192188262939453,-21.19485092163086,-21.219676971435547,-21.15575408935547,-21.18446159362793,-21.241405487060547,-21.190471649169922,-21.15924644470215,-21.176729202270508,-21.161457061767578,-21.22433090209961,-21.19303321838379,-21.148517608642578,-21.185453414916992,-21.18874168395996,-21.16629409790039,-21.17179298400879,-21.176050186157227,-21.20432472229004,-21.151809692382812,-21.187286376953125,-21.160234451293945,-21.182331085205078,-21.15343475341797,-21.173988342285156,-21.2176456451416,-21.19120216369629,-21.180389404296875,-21.14700698852539,-21.161428451538086,-21.204130172729492,-21.220964431762695,-21.202957153320312,-21.195537567138672,-21.205167770385742,-21.185531616210938,-21.179058074951172,-21.19376564025879,-21.193477630615234,-21.184215545654297,-21.205177307128906,-21.218961715698242,-21.217384338378906,-21.21656608581543,-21.22854995727539,-21.191659927368164,-21.221384048461914,-21.180034637451172,-21.20125961303711,-21.21364974975586,-21.200510025024414,-21.192691802978516,-21.201860427856445,-21.19411277770996,-21.20663070678711,-21.191024780273438,-21.20305633544922,-21.18794059753418,-21.19168472290039,-21.19644546508789,-21.196182250976562,-21.18429946899414,-21.18877410888672,-21.18156623840332,-21.19612693786621,-21.179941177368164,-21.19112777709961,-21.163429260253906,-21.177623748779297,-21.194318771362305,-21.20577621459961,-21.18557357788086,-21.183048248291016,-21.177453994750977,-21.193071365356445,-21.189672470092773,-21.188549041748047,-21.17580223083496,-21.178468704223633,-21.18808937072754,-21.194534301757812,-21.193946838378906,-21.222408294677734,-21.18509864807129,-21.190425872802734,-21.16306495666504,-21.178424835205078,-21.16999053955078,-21.16667366027832,-21.173751831054688,-21.176450729370117,-21.174362182617188,-21.172679901123047,-21.175466537475586,-21.166637420654297,-21.1597957611084,-21.166847229003906,-21.176197052001953,-21.156646728515625,-21.17440414428711,-21.176712036132812,-21.1755428314209,-21.179359436035156,-21.175430297851562,-21.181705474853516,-21.169010162353516,-21.125999450683594,-21.176382064819336,-21.18157958984375,-21.171323776245117,-21.17894172668457,-21.17275619506836,-21.167713165283203,-21.17938995361328,-21.17815399169922,-21.15677261352539,-21.181617736816406,-21.176437377929688,-21.176462173461914,-21.17544937133789,-21.174814224243164,-21.177270889282227,-21.182313919067383,-21.17267608642578,-21.178281784057617,-21.181833267211914,-21.179162979125977,-21.182750701904297,-21.176055908203125,-21.172147750854492,-21.172237396240234,-21.173709869384766,-21.176197052001953,-21.175338745117188,-21.174718856811523,-21.174713134765625,-21.174827575683594,-21.174976348876953,-21.17253303527832,-21.178197860717773,-21.172428131103516,-21.177690505981445,-21.17522430419922,-21.177799224853516,-21.176877975463867,-21.172903060913086,-21.165359497070312,-21.177492141723633,-21.175661087036133,-21.175874710083008,-21.177122116088867,-21.167316436767578,-21.176301956176758,-21.17131996154785,-21.17253303527832,-21.165510177612305,-21.16871452331543,-21.167987823486328,-21.16646385192871,-21.172752380371094,-21.166181564331055,-21.16400718688965,-21.1704044342041,-21.170000076293945,-21.169448852539062,-21.171052932739258,-21.16474723815918,-21.17154884338379,-21.168842315673828,-21.171525955200195,-21.16782569885254,-21.16626739501953,-21.162317276000977,-21.168935775756836,-21.166370391845703,-21.171939849853516,-21.171321868896484,-21.171628952026367,-21.123764038085938,-21.175579071044922,-21.17804718017578,-21.175609588623047,-21.176721572875977,-21.173871994018555,-21.174606323242188,-21.174211502075195,-21.176206588745117,-21.177257537841797,-21.17811393737793,-21.17856216430664,-21.17840003967285,-21.177894592285156,-21.179594039916992,-21.179197311401367,-21.179288864135742,-21.180702209472656,-21.181249618530273,-21.182838439941406,-21.184030532836914,-21.18389129638672,-21.184593200683594,-21.183046340942383,-21.183807373046875,-21.185592651367188,-21.18307113647461,-21.182512283325195,-21.182493209838867,-21.182374954223633,-21.181188583374023,-21.180736541748047,-21.180734634399414,-21.180015563964844,-21.179874420166016,-21.179397583007812,-21.17860984802246,-21.177871704101562,-21.178144454956055,-21.179290771484375,-21.179441452026367,-21.179664611816406,-21.18021583557129,-21.180477142333984,-21.180713653564453,-21.180831909179688,-21.18103790283203,-21.181968688964844],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"#EF553B","size":3},"mode":"markers","name":"cluster 1","x":[11.040688514709473,11.031713485717773,11.12254810333252,10.984821319580078,11.097211837768555,11.067927360534668,11.081522941589355,11.072831153869629,11.091265678405762,11.08938980102539,11.087153434753418,11.202468872070312,11.14620304107666,11.208555221557617,10.989105224609375,11.018509864807129,11.09496021270752,11.19086742401123,11.026339530944824,11.125434875488281,11.190818786621094,11.18094253540039,11.065406799316406,11.086917877197266,11.066757202148438,11.079793930053711,11.052305221557617,11.11273193359375,11.161458015441895,11.06901741027832,11.016122817993164,11.127897262573242,11.068906784057617,11.02608585357666,11.09229850769043,11.044685363769531,11.020624160766602,11.074897766113281,11.091011047363281,11.060977935791016,10.858081817626953,11.06019401550293,11.05172348022461,11.048332214355469,11.093926429748535,11.008708000183105,11.07732105255127,11.018827438354492,11.453993797302246,11.026481628417969,10.982136726379395,11.05575942993164,11.107019424438477,11.031973838806152,11.062077522277832,11.055871963500977,11.038240432739258,11.057568550109863,11.083189964294434,11.086280822753906,11.107148170471191,11.05433177947998,11.01754379272461,11.06934642791748,10.972406387329102,11.043876647949219,11.036164283752441,11.054344177246094,11.045486450195312,11.09752368927002,11.055269241333008,11.042317390441895,11.032730102539062,11.039542198181152,11.045306205749512,11.044328689575195,11.086005210876465,11.02127456665039,11.273771286010742,11.041048049926758,11.032694816589355,10.997481346130371,11.081184387207031,11.037507057189941,11.065933227539062,11.002199172973633,11.083403587341309,11.00819206237793,10.966994285583496,11.045735359191895,11.058917999267578,11.07610034942627,10.995817184448242,11.078651428222656,11.082855224609375,11.02498722076416,11.03891658782959,11.028240203857422,11.039278030395508,11.071167945861816,11.021994590759277,11.05845832824707,11.037432670593262,11.004162788391113,11.005633354187012,11.017789840698242,11.029693603515625,11.035404205322266,11.062156677246094,10.97578239440918,11.03252124786377,11.053558349609375,11.027836799621582,11.000901222229004,11.03522777557373,11.02701473236084,11.01838207244873,11.008888244628906,11.04114055633545,11.02763557434082,11.001277923583984,11.03759765625,11.018993377685547,11.038582801818848,11.031793594360352,11.047767639160156,10.992134094238281,11.048627853393555,11.041584014892578,11.051509857177734,11.028844833374023,11.040782928466797,11.057184219360352,11.04648494720459,11.04040813446045,11.047383308410645,11.049666404724121,11.043902397155762,11.02326774597168,11.067696571350098,11.032690048217773,11.043927192687988,11.0250244140625,11.038678169250488,11.034354209899902,11.02824592590332,11.031964302062988,11.022496223449707,11.040892601013184,11.039325714111328,11.045235633850098,11.04586410522461,11.054502487182617,11.034579277038574,11.038290023803711,11.033062934875488,11.032395362854004,11.042941093444824,11.026325225830078,11.007328033447266,11.036523818969727,11.030712127685547,11.044057846069336,11.051685333251953,11.036245346069336,11.027505874633789,11.037775039672852,11.02819538116455,11.02643871307373,11.0249605178833,11.039807319641113,11.033167839050293,11.037492752075195,11.030317306518555,11.029400825500488,11.03487491607666,11.026877403259277,11.034464836120605,11.026040077209473,11.034555435180664,11.025196075439453,11.043498039245605,11.03441047668457,11.036116600036621,11.02855110168457,11.035284042358398,11.028809547424316,11.029900550842285,11.034685134887695,11.031847953796387,11.026305198669434,11.035171508789062,11.021280288696289,11.031740188598633,11.037603378295898,11.035429000854492,11.023322105407715,11.040328979492188,11.042057037353516,11.040553092956543,11.036663055419922,11.03954792022705,11.037385940551758,11.041695594787598,11.033726692199707,11.026843070983887,11.03400993347168,9.612569808959961,11.031320571899414,11.037123680114746,11.01982593536377,11.028324127197266,11.029317855834961,11.024824142456055,11.030896186828613,11.02725601196289,11.036352157592773,11.029510498046875,11.029914855957031,11.026103019714355,11.02257251739502,11.021437644958496,11.00247573852539,11.026708602905273,11.028742790222168,11.016083717346191,11.031558990478516,11.028558731079102,11.037412643432617,11.037369728088379,11.012495040893555,11.041360855102539,11.034185409545898,11.03728199005127,11.040336608886719,11.03894329071045,11.041385650634766,11.045445442199707,11.036142349243164,11.026283264160156,11.038796424865723,11.04163932800293,11.038537979125977,11.039138793945312,11.038019180297852,11.037529945373535,11.037965774536133,11.006393432617188,11.042746543884277,11.043293952941895],"y":[10.849989891052246,10.807523727416992,10.930765151977539,10.897150993347168,10.822357177734375,10.87387466430664,10.741902351379395,10.799595832824707,10.888920783996582,10.95953369140625,10.846522331237793,10.91064739227295,10.850955963134766,10.80493450164795,10.874788284301758,10.81840991973877,10.819771766662598,10.86494255065918,10.921643257141113,10.7579984664917,10.772549629211426,10.887763023376465,10.791929244995117,10.925702095031738,10.860048294067383,10.839930534362793,10.822063446044922,10.824180603027344,10.778216361999512,10.787094116210938,10.787623405456543,10.803601264953613,10.79877758026123,10.887632369995117,10.831031799316406,10.843472480773926,10.911697387695312,10.914588928222656,10.857805252075195,10.814223289489746,10.831915855407715,10.895621299743652,10.887465476989746,10.771378517150879,10.845003128051758,10.904138565063477,10.821882247924805,10.874059677124023,10.867167472839355,10.882553100585938,10.872293472290039,10.856781959533691,10.74425983428955,10.864784240722656,10.844112396240234,10.870671272277832,10.860785484313965,10.815666198730469,10.833251953125,10.7409086227417,10.83884334564209,10.902321815490723,10.79311466217041,10.874481201171875,10.860586166381836,10.860939025878906,10.866085052490234,10.848517417907715,10.84439468383789,10.78519344329834,10.880579948425293,10.840103149414062,10.846946716308594,10.827985763549805,10.815776824951172,10.808384895324707,10.858366966247559,10.8149995803833,10.799537658691406,10.840441703796387,10.836817741394043,10.796451568603516,10.887946128845215,10.870206832885742,10.855478286743164,10.835895538330078,10.886211395263672,10.827308654785156,10.806477546691895,10.866140365600586,10.826495170593262,10.830623626708984,10.861604690551758,10.866288185119629,10.830729484558105,10.871990203857422,10.834999084472656,10.869589805603027,10.849305152893066,10.825150489807129,10.835911750793457,10.827917098999023,10.830541610717773,10.833215713500977,10.830574035644531,10.819284439086914,10.853174209594727,10.812152862548828,10.818154335021973,10.845271110534668,10.845184326171875,10.830498695373535,10.860328674316406,10.868528366088867,10.859260559082031,10.870467185974121,10.823328018188477,10.83891773223877,10.838923454284668,10.833434104919434,10.838789939880371,10.841362953186035,10.834833145141602,10.833803176879883,10.841261863708496,10.82947826385498,10.835552215576172,10.811617851257324,10.846670150756836,10.835419654846191,10.835084915161133,10.816818237304688,10.790060997009277,10.818987846374512,10.849016189575195,10.832655906677246,10.826689720153809,10.834430694580078,10.8342866897583,10.816608428955078,10.826520919799805,10.824692726135254,10.8268461227417,10.837088584899902,10.832857131958008,10.840531349182129,10.839960098266602,10.825577735900879,10.831275939941406,10.837203979492188,10.825386047363281,10.836304664611816,10.839999198913574,10.850456237792969,10.841279029846191,10.83449935913086,10.846718788146973,10.828052520751953,10.841025352478027,10.834891319274902,10.835407257080078,10.834785461425781,10.83264446258545,10.845129013061523,10.830912590026855,10.835836410522461,10.831488609313965,10.839923858642578,10.837299346923828,10.826611518859863,10.835700035095215,10.83704662322998,10.833279609680176,10.839701652526855,10.840328216552734,10.843368530273438,10.84334945678711,10.84345531463623,10.836880683898926,10.836382865905762,10.837496757507324,10.835653305053711,10.835770606994629,10.837867736816406,10.840892791748047,10.83581829071045,10.8340425491333,10.83154582977295,10.834304809570312,10.834454536437988,10.83049488067627,10.836153030395508,10.837530136108398,10.830469131469727,10.82907772064209,10.833497047424316,10.825621604919434,10.829431533813477,10.834989547729492,10.828726768493652,10.830181121826172,10.826297760009766,10.824581146240234,10.826641082763672,10.82937240600586,10.8268461227417,10.827208518981934,12.812036514282227,10.836442947387695,10.833427429199219,10.834006309509277,10.8328857421875,10.832486152648926,10.834151268005371,10.832328796386719,10.835570335388184,10.831500053405762,10.831905364990234,10.830666542053223,10.836743354797363,10.83678150177002,10.840246200561523,10.838523864746094,10.83694076538086,10.836584091186523,10.840079307556152,10.83693790435791,10.839264869689941,10.835829734802246,10.833722114562988,10.825145721435547,10.835627555847168,10.839168548583984,10.836159706115723,10.834779739379883,10.835862159729004,10.830758094787598,10.837015151977539,10.841020584106445,10.843799591064453,10.841381072998047,10.8390474319458,10.842558860778809,10.841835975646973,10.841649055480957,10.841943740844727,10.842597007751465,10.847579002380371,10.8422269821167,10.841623306274414],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"#00CC96","size":3},"mode":"markers","name":"cluster 2","x":[-18.92998695373535,-18.720666885375977,-18.766525268554688,-18.637042999267578,-18.616186141967773,-18.7513484954834,-18.715757369995117,-18.569238662719727,-18.655000686645508,-18.751527786254883,-18.697402954101562,-18.650711059570312,-18.66461753845215,-18.769508361816406,-18.673959732055664,-18.726865768432617,-18.711111068725586,-18.63826560974121,-18.640243530273438,-18.661087036132812,-18.716379165649414,-18.728384017944336,-18.77264404296875,-18.810768127441406,-18.716672897338867,-18.711673736572266,-18.6966552734375,-18.61363410949707,-18.87141227722168,-18.766149520874023,-18.67243003845215,-18.708873748779297,-18.73546028137207,-18.867876052856445,-18.683563232421875,-18.733108520507812,-18.700489044189453,-18.65186882019043,-18.67190933227539,-18.766050338745117,-18.790956497192383,-18.686847686767578,-18.677583694458008,-18.7247257232666,-18.69346046447754,-18.711103439331055,-18.750652313232422,-18.720413208007812,-18.774433135986328,-18.76922607421875,-18.733367919921875,-18.74512481689453,-18.71184539794922,-18.710371017456055,-18.799522399902344,-18.80047607421875,-18.75269317626953,-18.784013748168945,-18.737092971801758,-18.80876922607422,-18.836023330688477,-18.7557430267334,-18.781320571899414,-18.768648147583008,-18.758621215820312,-18.73202896118164,-18.713979721069336,-18.65401840209961,-18.699840545654297,-18.74823570251465,-18.755281448364258,-18.705045700073242,-18.750951766967773,-18.755168914794922,-18.731037139892578,-18.798887252807617,-18.881893157958984,-18.70503044128418,-18.74014663696289,-18.71316146850586,-18.64777183532715,-18.800201416015625,-18.72157096862793,-18.705175399780273,-18.757747650146484,-18.74981689453125,-18.716398239135742,-18.7286319732666,-18.703943252563477,-18.702768325805664,-18.736112594604492,-18.697757720947266,-18.732837677001953,-18.808013916015625,-18.747957229614258,-18.715646743774414,-18.692350387573242,-18.732275009155273,-18.700376510620117,-18.743715286254883,-18.714548110961914,-18.72465705871582,-18.721738815307617,-18.742551803588867,-18.712818145751953,-18.71422576904297,-18.689407348632812,-18.69123077392578,-18.730249404907227,-18.699106216430664,-18.722810745239258,-18.712717056274414,-18.78722381591797,-18.716205596923828,-18.70326042175293,-18.728858947753906,-18.72617530822754,-18.73290252685547,-18.714948654174805,-18.740276336669922,-18.733985900878906,-18.717451095581055,-18.726268768310547,-18.73082160949707,-18.720617294311523,-18.71811294555664,-18.742652893066406,-18.75383758544922,-18.727691650390625,-18.71364974975586,-18.713645935058594,-18.716041564941406,-18.725318908691406,-18.740297317504883,-18.719451904296875,-18.719573974609375,-18.720069885253906,-18.720558166503906,-18.70854949951172,-18.72667694091797,-18.724645614624023,-18.72314453125,-18.725784301757812,-18.730487823486328,-18.716339111328125,-18.720022201538086,-18.721471786499023,-18.71897315979004,-18.722986221313477,-18.725589752197266,-18.71724510192871,-18.726808547973633,-18.72393798828125,-18.72014617919922,-18.725980758666992,-18.72844696044922,-18.726491928100586,-18.733257293701172,-18.725893020629883,-18.71855354309082,-18.722270965576172,-18.729623794555664,-18.736011505126953,-18.732444763183594,-18.7349910736084,-18.730405807495117,-18.717363357543945,-18.717941284179688,-18.721118927001953,-18.722475051879883,-18.72243881225586,-18.714799880981445,-18.711580276489258,-18.71416664123535,-18.723094940185547,-18.71556282043457,-18.717023849487305,-18.71710205078125,-18.715057373046875,-18.72257423400879,-18.717458724975586,-18.717357635498047,-18.718530654907227,-18.714956283569336,-18.715707778930664,-18.721057891845703,-18.7111759185791,-18.710472106933594,-18.709238052368164,-18.707836151123047,-18.71306610107422,-18.71410369873047,-18.715463638305664,-18.71522331237793,-18.711774826049805,-18.711496353149414,-18.71533203125,-18.713441848754883,-18.715286254882812,-18.71815299987793,-18.71628189086914,-18.714704513549805,-18.714744567871094,-18.714134216308594,-18.711252212524414,-18.7133731842041,-18.71321678161621,-18.7086124420166,-18.71017074584961,-18.717700958251953,-18.712913513183594,-18.714860916137695,-18.71912384033203,-18.719877243041992,-18.719316482543945,-18.72234344482422,-18.72138786315918,-18.720539093017578,-18.72081756591797,-18.720380783081055,-18.7205753326416,-18.719863891601562,-18.71996307373047,-18.717918395996094,-18.71721649169922,-18.717172622680664,-18.71927833557129,-18.71709442138672,-18.717222213745117,-18.7164306640625,-18.717056274414062,-18.718461990356445,-18.720474243164062,-18.71805763244629,-18.719593048095703,-18.719942092895508,-18.718917846679688,-18.719324111938477,-18.722209930419922,-18.72274398803711,-18.722604751586914,-18.723295211791992,-18.72429084777832,-18.724695205688477,-18.724225997924805,-18.723783493041992,-18.724258422851562,-18.724027633666992,-18.723569869995117,-18.723590850830078],"y":[-5.3332037925720215,-5.467034339904785,-5.418692111968994,-5.489316463470459,-5.569392681121826,-5.435245990753174,-5.44850492477417,-5.501718997955322,-5.629614353179932,-5.440014362335205,-5.496533393859863,-5.549383640289307,-5.548647403717041,-5.477458477020264,-5.459098815917969,-5.441924095153809,-5.5091376304626465,-5.438892364501953,-5.507137775421143,-5.519532203674316,-5.457067012786865,-5.493835926055908,-5.439650058746338,-5.436712265014648,-5.462392330169678,-5.490437984466553,-5.503962516784668,-5.518239498138428,-5.377710342407227,-5.451091766357422,-5.476663589477539,-5.453900337219238,-5.45320987701416,-5.367488861083984,-5.536747932434082,-5.456981182098389,-5.452523708343506,-5.534592151641846,-5.511948108673096,-5.4175190925598145,-5.406425476074219,-5.452805519104004,-5.496840000152588,-5.54269552230835,-5.467154502868652,-5.302204608917236,-5.460704803466797,-5.482011318206787,-5.442381381988525,-5.497282028198242,-5.47032356262207,-5.424581527709961,-5.468878746032715,-5.418523788452148,-5.4523749351501465,-5.402653217315674,-5.478524208068848,-5.478963375091553,-5.440783500671387,-5.413897514343262,-5.421545028686523,-5.415806770324707,-5.478338241577148,-5.4728007316589355,-5.453310489654541,-5.500853538513184,-5.485206604003906,-5.452327251434326,-5.470252990722656,-5.468576431274414,-5.4214091300964355,-5.486116409301758,-5.456018447875977,-5.461915016174316,-5.481311798095703,-5.469416618347168,-5.438508987426758,-5.50455904006958,-5.466264724731445,-5.522637367248535,-5.566802501678467,-5.530477523803711,-5.405311107635498,-5.450909614562988,-5.441859722137451,-5.455995559692383,-5.431947708129883,-5.482185363769531,-5.476840019226074,-5.506064414978027,-5.480032920837402,-5.481909275054932,-5.485936641693115,-5.478034019470215,-5.4739155769348145,-5.49893045425415,-5.508979797363281,-5.434871673583984,-5.511185646057129,-5.467153072357178,-5.471264839172363,-5.488300323486328,-5.43789005279541,-5.458642959594727,-5.490581512451172,-5.475409984588623,-5.486885070800781,-5.464430809020996,-5.460434913635254,-5.496809005737305,-5.486924171447754,-5.487839221954346,-5.424887180328369,-5.480360984802246,-5.488858222961426,-5.44986629486084,-5.464628219604492,-5.46260404586792,-5.483794689178467,-5.456790447235107,-5.4632697105407715,-5.457845211029053,-5.463356018066406,-5.471694469451904,-5.472960948944092,-5.482985973358154,-5.473097324371338,-5.457923412322998,-5.468649387359619,-5.465460300445557,-5.482517242431641,-5.482532024383545,-5.476871490478516,-5.464221477508545,-5.488717555999756,-5.470710754394531,-5.464620113372803,-5.4822306632995605,-5.4644646644592285,-5.471458435058594,-5.481785297393799,-5.475836277008057,-5.472967624664307,-5.465854167938232,-5.479508876800537,-5.465227127075195,-5.488491535186768,-5.476752758026123,-5.478104591369629,-5.4900126457214355,-5.483054161071777,-5.469735622406006,-5.4726362228393555,-5.4763617515563965,-5.470552921295166,-5.462282180786133,-5.476377964019775,-5.469763278961182,-5.4676432609558105,-5.478931427001953,-5.48682165145874,-5.4834208488464355,-5.464050769805908,-5.491449356079102,-5.458889961242676,-5.4714555740356445,-5.490318775177002,-5.490229606628418,-5.485439300537109,-5.483020305633545,-5.489905834197998,-5.494791507720947,-5.497315883636475,-5.496468544006348,-5.480217933654785,-5.4887166023254395,-5.48224401473999,-5.488049507141113,-5.491960048675537,-5.4683732986450195,-5.488794803619385,-5.490234851837158,-5.486958026885986,-5.496905326843262,-5.489160537719727,-5.479425430297852,-5.497380256652832,-5.495127201080322,-5.490752696990967,-5.486353397369385,-5.490183353424072,-5.495081901550293,-5.490310192108154,-5.4903950691223145,-5.495438098907471,-5.491747856140137,-5.483425140380859,-5.4841718673706055,-5.480940341949463,-5.4784955978393555,-5.481290340423584,-5.480283737182617,-5.478245735168457,-5.480992317199707,-5.48258638381958,-5.480163097381592,-5.48038911819458,-5.480784893035889,-5.488403797149658,-5.477826118469238,-5.480833530426025,-5.4768829345703125,-5.475019454956055,-5.4730377197265625,-5.473536968231201,-5.47443962097168,-5.473276138305664,-5.472804546356201,-5.470997333526611,-5.471521854400635,-5.471799850463867,-5.4703593254089355,-5.471290111541748,-5.472489356994629,-5.473406791687012,-5.473467826843262,-5.472222805023193,-5.473320484161377,-5.47197961807251,-5.471767425537109,-5.472597599029541,-5.47067928314209,-5.468782901763916,-5.471737384796143,-5.471879959106445,-5.471511363983154,-5.471887111663818,-5.472707748413086,-5.473812580108643,-5.473499774932861,-5.475783348083496,-5.475623607635498,-5.474576950073242,-5.473781108856201,-5.473714351654053,-5.47443962097168,-5.474031925201416,-5.473941326141357,-5.474493503570557,-5.473453044891357],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"#AB63FA","size":3},"mode":"markers","name":"cluster 3","x":[-20.551555633544922,-20.688491821289062,-20.560882568359375,-20.557628631591797,-20.57139778137207,-20.55912971496582,-20.604894638061523,-20.63631248474121,-20.60969352722168,-20.578060150146484,-20.612260818481445,-20.63347625732422,-20.628311157226562,-20.606374740600586,-20.576396942138672,-20.58623695373535,-20.623735427856445,-20.569355010986328,-20.556724548339844,-20.6245059967041,-20.59547996520996,-20.640453338623047,-20.680875778198242,-20.6795597076416,-20.626237869262695,-20.587303161621094,-20.592466354370117,-20.65968894958496,-20.637920379638672,-20.643741607666016,-20.5328311920166,-20.591623306274414,-20.627851486206055,-20.65214729309082,-20.596357345581055,-20.623281478881836,-20.625442504882812,-20.63762092590332,-20.54523277282715,-20.648143768310547,-20.62606430053711,-20.619531631469727,-20.618684768676758,-20.60999870300293,-20.58275604248047,-20.589981079101562,-20.602096557617188,-20.589946746826172,-20.581945419311523,-20.6058292388916,-20.600406646728516,-20.636457443237305,-20.577770233154297,-20.618419647216797,-20.646188735961914,-20.603605270385742,-20.611631393432617,-20.63123321533203,-20.61072540283203,-20.579402923583984,-20.609668731689453,-20.602581024169922,-20.64341163635254,-20.60491180419922,-20.610342025756836,-20.589311599731445,-20.583614349365234,-20.612337112426758,-20.607913970947266,-20.59331512451172,-20.557661056518555,-20.59337615966797,-20.555261611938477,-20.58728790283203,-20.606632232666016,-20.586036682128906,-20.621505737304688,-20.578105926513672,-20.590200424194336,-20.584457397460938,-20.588157653808594,-20.58953094482422,-20.571449279785156,-20.580310821533203,-20.58150863647461,-20.578035354614258,-20.604249954223633,-20.620454788208008,-20.62005043029785,-20.591819763183594,-20.56329917907715,-20.57933235168457,-20.594757080078125,-20.58005714416504,-20.583322525024414,-20.585783004760742,-20.58811378479004,-20.593503952026367,-20.588430404663086,-20.5874080657959,-20.575096130371094,-20.579761505126953,-20.56283950805664,-20.567584991455078,-20.58318328857422,-20.56926727294922,-20.572935104370117,-20.59415054321289,-20.57989501953125,-20.576433181762695,-20.580106735229492,-20.548519134521484,-20.582324981689453,-20.58898162841797,-20.58139419555664,-20.584070205688477,-20.591514587402344,-20.580373764038086,-20.574392318725586,-20.580354690551758,-20.573501586914062,-20.575748443603516,-20.5756778717041,-20.57206916809082,-20.586929321289062,-20.581100463867188,-20.57326316833496,-20.587434768676758,-20.586240768432617,-20.57402801513672,-20.580434799194336,-20.580263137817383,-20.587047576904297,-20.57774543762207,-20.594329833984375,-20.579254150390625,-20.58698844909668,-20.578596115112305,-20.576509475708008,-20.577878952026367,-20.580114364624023,-20.580869674682617,-20.574081420898438,-20.578388214111328,-20.571258544921875,-20.571107864379883,-20.583295822143555,-20.583538055419922,-20.587438583374023,-20.58167266845703,-20.57411003112793,-20.58865737915039,-20.586719512939453,-20.59372329711914,-20.589168548583984,-20.58429718017578,-20.592161178588867,-20.589374542236328,-20.588428497314453,-20.587791442871094,-20.587793350219727,-20.594539642333984,-20.589975357055664,-20.588973999023438,-20.582487106323242,-20.5875244140625,-20.59275245666504,-20.591493606567383,-20.59193229675293,-20.591291427612305,-20.590099334716797,-20.592811584472656,-20.59776496887207,-20.59780502319336,-20.59810447692871,-20.597061157226562,-20.597545623779297,-20.598413467407227,-20.60312271118164,-20.59849739074707,-20.59754180908203,-20.59915542602539,-20.59942054748535,-20.601144790649414,-20.600460052490234,-20.599817276000977,-20.59974479675293,-20.598581314086914,-20.598011016845703,-20.59781837463379,-20.59748077392578,-20.596710205078125,-20.596166610717773,-20.598127365112305,-20.599037170410156,-20.600542068481445,-20.600797653198242,-20.59805679321289,-20.602394104003906,-20.60099983215332,-20.601943969726562,-20.60189437866211,-20.603286743164062,-20.602998733520508,-20.60247039794922,-20.60221290588379,-20.601716995239258,-20.6020450592041,-20.602537155151367,-20.60228729248047,-20.602840423583984,-20.602981567382812,-20.602235794067383,-20.602304458618164,-20.603364944458008,-20.602916717529297,-20.601943969726562,-20.601211547851562,-20.60092544555664,-20.601276397705078,-20.601045608520508,-20.60257339477539,-20.603118896484375,-20.603477478027344,-20.599393844604492,-20.599273681640625,-20.59868621826172,-20.598478317260742,-20.597986221313477,-20.59705924987793,-20.597251892089844,-20.596216201782227,-20.597442626953125,-20.59613609313965,-20.597347259521484,-20.59755516052246,-20.597566604614258,-20.59786605834961,-20.59772300720215,-20.596961975097656,-20.597177505493164,-20.597553253173828,-20.5971736907959,-20.596420288085938,-20.596275329589844,-20.596588134765625,-20.595666885375977,-20.59552001953125,-20.596094131469727,-20.59604263305664],"y":[8.955490112304688,9.029621124267578,9.089629173278809,9.062684059143066,9.171809196472168,8.976901054382324,9.167901992797852,9.08367919921875,9.106653213500977,9.12701416015625,9.131611824035645,9.114015579223633,8.98703384399414,9.074772834777832,9.074496269226074,9.020186424255371,8.962052345275879,9.043229103088379,9.104615211486816,9.097284317016602,9.104016304016113,9.064221382141113,9.064542770385742,9.201543807983398,9.022647857666016,9.091791152954102,9.14824104309082,9.11501407623291,9.129739761352539,9.0470609664917,9.043758392333984,9.094799995422363,9.134201049804688,9.194087982177734,9.199978828430176,9.104838371276855,9.144147872924805,9.174040794372559,9.096026420593262,9.054192543029785,9.137478828430176,9.096165657043457,9.115607261657715,9.15400505065918,9.130227088928223,9.130101203918457,9.173624038696289,9.108187675476074,9.131756782531738,9.142468452453613,9.139372825622559,9.157238960266113,9.164351463317871,9.104854583740234,9.164180755615234,9.128585815429688,9.132003784179688,9.12484073638916,9.068662643432617,9.083104133605957,9.114675521850586,9.11724853515625,9.18464469909668,9.081046104431152,9.156888008117676,9.14656925201416,9.1014404296875,9.102401733398438,9.11836051940918,9.040160179138184,9.083050727844238,9.13653564453125,9.117923736572266,9.117595672607422,9.105432510375977,9.122875213623047,9.155608177185059,9.118431091308594,9.127345085144043,9.124390602111816,9.139152526855469,9.13542366027832,9.133233070373535,9.07659912109375,9.087237358093262,9.150997161865234,9.093507766723633,9.12891960144043,9.052927017211914,9.079586029052734,9.115869522094727,9.127697944641113,9.109880447387695,9.096589088439941,9.095311164855957,9.120820045471191,9.110925674438477,9.099928855895996,9.101941108703613,9.07705020904541,9.083588600158691,9.114034652709961,9.094086647033691,9.09846305847168,9.110424995422363,9.09274959564209,9.077444076538086,9.139662742614746,9.095401763916016,9.072011947631836,9.090441703796387,9.058501243591309,9.104187965393066,9.100488662719727,9.098751068115234,9.118456840515137,9.12437629699707,9.112318992614746,9.088428497314453,9.095137596130371,9.066107749938965,9.107138633728027,9.134516716003418,9.101537704467773,9.098076820373535,9.108830451965332,9.073482513427734,9.103534698486328,9.096073150634766,9.086308479309082,9.106143951416016,9.08802318572998,9.055953979492188,9.086708068847656,9.122417449951172,9.119708061218262,9.106822967529297,9.098220825195312,9.095414161682129,9.093032836914062,9.101752281188965,9.099590301513672,9.10312557220459,9.104896545410156,9.080949783325195,9.09860897064209,9.101847648620605,9.086292266845703,9.1051607131958,9.096025466918945,9.101527214050293,9.097800254821777,9.08899211883545,9.10597038269043,9.098731994628906,9.100492477416992,9.09580135345459,9.096609115600586,9.098631858825684,9.090105056762695,9.097040176391602,9.10167121887207,9.095355033874512,9.092857360839844,9.073519706726074,9.087742805480957,9.088109016418457,9.09883975982666,9.095986366271973,9.101550102233887,9.089110374450684,9.093825340270996,9.092769622802734,9.094923973083496,9.093682289123535,9.090642929077148,9.091238975524902,9.089238166809082,9.090542793273926,9.097701072692871,9.091629981994629,9.098408699035645,9.094683647155762,9.098523139953613,9.096748352050781,9.092144012451172,9.092988967895508,9.091437339782715,9.093300819396973,9.094481468200684,9.096080780029297,9.09443187713623,9.091684341430664,9.095869064331055,9.094831466674805,9.096344947814941,9.092204093933105,9.093338012695312,9.09557056427002,9.092723846435547,9.094072341918945,9.093475341796875,9.094161987304688,9.093056678771973,9.094664573669434,9.092374801635742,9.093730926513672,9.095303535461426,9.093425750732422,9.093466758728027,9.095428466796875,9.098526954650879,9.097488403320312,9.096638679504395,9.095808029174805,9.099020957946777,9.097855567932129,9.097014427185059,9.097285270690918,9.097268104553223,9.096689224243164,9.09729290008545,9.097887992858887,9.098639488220215,9.100333213806152,9.100061416625977,9.099075317382812,9.098201751708984,9.09920883178711,9.099272727966309,9.098628997802734,9.100069046020508,9.099513053894043,9.100409507751465,9.100923538208008,9.101470947265625,9.102407455444336,9.102428436279297,9.102291107177734,9.101527214050293,9.101314544677734,9.100908279418945,9.102001190185547,9.10138988494873,9.101415634155273,9.101140975952148,9.101716041564941,9.099580764770508,9.099532127380371,9.099261283874512],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"#FFA15A","size":3},"mode":"markers","name":"cluster 4","x":[-9.621533393859863,-9.717039108276367,-9.71152400970459,-9.650535583496094,-9.62956428527832,-9.694857597351074,-9.50988483428955,-9.640463829040527,-9.668008804321289,-9.567523002624512,-9.744732856750488,-9.60798168182373,-9.672917366027832,-9.627241134643555,-9.663293838500977,-9.705881118774414,-9.582287788391113,-9.700662612915039,-9.730525016784668,-9.608135223388672,-9.656582832336426,-9.656076431274414,-9.621407508850098,-9.663220405578613,-9.604072570800781,-9.65703296661377,-9.733193397521973,-9.768857955932617,-9.624792098999023,-9.585394859313965,-9.537278175354004,-9.6410551071167,-9.605502128601074,-9.621761322021484,-9.617735862731934,-9.6592378616333,-9.59302043914795,-9.662397384643555,-9.582121849060059,-9.565933227539062,-9.62994384765625,-9.621601104736328,-9.624109268188477,-9.684459686279297,-9.540498733520508,-9.662293434143066,-9.622213363647461,-9.625581741333008,-9.656530380249023,-9.684139251708984,-9.647799491882324,-9.607878684997559,-9.696170806884766,-9.6650972366333,-9.619061470031738,-9.614598274230957,-9.646873474121094,-9.62224292755127,-9.629754066467285,-9.620041847229004,-9.681096076965332,-9.640727043151855,-9.64243221282959,-9.657028198242188,-9.635662078857422,-9.618314743041992,-9.657310485839844,-9.654059410095215,-9.605037689208984,-9.6063871383667,-9.626546859741211,-9.633030891418457,-9.613364219665527,-9.615514755249023,-9.600936889648438,-9.634247779846191,-9.639535903930664,-9.668240547180176,-9.757271766662598,-9.624083518981934,-9.616072654724121,-9.62983512878418,-9.622544288635254,-9.626115798950195,-9.637157440185547,-9.680312156677246,-9.692164421081543,-9.617741584777832,-9.637927055358887,-9.616829872131348,-9.620138168334961,-9.63525676727295,-9.624791145324707,-9.627814292907715,-9.617288589477539,-9.60728931427002,-9.604372024536133,-9.61330509185791,-9.611381530761719,-9.623998641967773,-9.630359649658203,-9.637113571166992,-9.62145709991455,-9.605756759643555,-9.627212524414062,-9.618345260620117,-9.609780311584473,-9.62374496459961,-9.626213073730469,-9.6342191696167,-9.648076057434082,-9.625211715698242,-9.620673179626465,-9.640307426452637,-9.629265785217285,-9.634556770324707,-9.632621765136719,-9.64359188079834,-9.644036293029785,-9.639789581298828,-9.633946418762207,-9.635464668273926,-9.628403663635254,-9.630058288574219,-9.636674880981445,-9.634364128112793,-9.631611824035645,-9.633455276489258,-9.630448341369629,-9.629206657409668,-9.638948440551758,-9.619990348815918,-9.632278442382812,-9.626375198364258,-9.627729415893555,-9.621169090270996,-9.621600151062012,-9.622735977172852,-9.634157180786133,-9.623815536499023,-9.621397972106934,-9.621484756469727,-9.620774269104004,-9.614437103271484,-9.624735832214355,-9.627310752868652,-9.616491317749023,-9.625310897827148,-9.62380313873291,-9.615436553955078,-9.614460945129395,-9.62028694152832,-9.624578475952148,-9.621201515197754,-9.624505043029785,-9.622030258178711,-9.629308700561523,-9.633350372314453,-9.630471229553223,-9.621685981750488,-9.631961822509766,-9.631433486938477,-9.632122039794922,-9.634389877319336,-9.640947341918945,-9.637042999267578,-9.63217830657959,-9.63262939453125,-9.638813018798828,-9.636959075927734,-9.633530616760254,-9.635309219360352,-9.634821891784668,-9.63337516784668,-9.631490707397461,-9.633713722229004,-9.630828857421875,-9.634197235107422,-9.639420509338379,-9.63758659362793,-9.637561798095703,-9.638486862182617,-9.638450622558594,-9.638387680053711,-9.639389038085938,-9.635228157043457,-9.635041236877441,-9.636730194091797,-9.634326934814453,-9.633393287658691,-9.634490966796875,-9.633868217468262,-9.633455276489258,-9.635111808776855,-9.634538650512695,-9.635382652282715,-9.63399887084961,-9.637092590332031,-9.63952922821045,-9.636042594909668,-9.637296676635742,-9.63818073272705,-9.640551567077637,-9.641610145568848,-9.641247749328613,-9.642607688903809,-9.641992568969727,-9.643375396728516,-9.643967628479004,-9.643016815185547,-9.641338348388672,-9.64029312133789,-9.639681816101074,-9.639887809753418,-9.639554023742676,-9.6400785446167,-9.638710021972656,-9.63929557800293,-9.63902473449707,-9.638145446777344,-9.638184547424316,-9.639507293701172,-9.638998031616211,-9.63878059387207,-9.63946533203125,-9.639030456542969,-9.63872241973877,-9.638199806213379,-9.63905143737793,-9.638334274291992,-9.638031005859375,-9.638482093811035,-9.638789176940918,-9.637368202209473,-9.640047073364258,-9.640379905700684,-9.639705657958984,-9.640162467956543,-9.63859748840332,-9.639374732971191,-9.638118743896484,-9.636750221252441,-9.637078285217285,-9.637048721313477,-9.636038780212402,-9.635473251342773,-9.635865211486816,-9.635677337646484,-9.635650634765625,-9.636067390441895],"y":[24.459278106689453,24.508535385131836,24.533023834228516,24.559621810913086,24.423389434814453,24.60299301147461,24.461997985839844,24.50011444091797,24.563644409179688,24.585365295410156,24.556255340576172,24.51999855041504,24.444698333740234,24.517473220825195,24.509368896484375,24.486082077026367,24.61408233642578,24.53005599975586,24.350975036621094,24.550390243530273,24.49297332763672,24.536325454711914,24.51529884338379,24.5189151763916,24.558738708496094,24.523502349853516,24.48012924194336,24.499319076538086,24.54253578186035,24.432662963867188,24.64282989501953,24.501279830932617,24.5045108795166,24.496795654296875,24.426240921020508,24.545454025268555,24.51238250732422,24.483158111572266,24.42315673828125,24.56180763244629,24.426259994506836,24.426706314086914,24.53644371032715,24.499156951904297,24.485004425048828,24.497085571289062,24.589677810668945,24.472108840942383,24.478269577026367,24.550045013427734,24.512195587158203,24.57448387145996,24.423490524291992,24.52682113647461,24.5291805267334,24.434946060180664,24.552526473999023,24.477563858032227,24.52361297607422,24.559494018554688,24.49919891357422,24.544221878051758,24.506860733032227,24.51282501220703,24.470312118530273,24.48687744140625,24.53462028503418,24.490463256835938,24.44913673400879,24.50921630859375,24.55754852294922,24.55295753479004,24.49798583984375,24.52898406982422,24.422990798950195,24.445842742919922,24.497695922851562,24.457555770874023,24.453840255737305,24.49189567565918,24.569860458374023,24.512958526611328,24.50165367126465,24.484394073486328,24.4880313873291,24.48129653930664,24.470752716064453,24.540319442749023,24.4589786529541,24.48219108581543,24.526935577392578,24.52914810180664,24.496055603027344,24.521602630615234,24.507150650024414,24.52217674255371,24.488998413085938,24.512813568115234,24.488876342773438,24.515872955322266,24.52640724182129,24.502643585205078,24.494930267333984,24.489810943603516,24.51494789123535,24.453489303588867,24.493860244750977,24.510128021240234,24.516313552856445,24.50798797607422,24.505754470825195,24.523029327392578,24.5195369720459,24.508441925048828,24.52276039123535,24.5141544342041,24.495248794555664,24.513734817504883,24.48360824584961,24.509517669677734,24.523609161376953,24.506410598754883,24.529735565185547,24.529272079467773,24.525732040405273,24.512292861938477,24.51223373413086,24.506362915039062,24.49674415588379,24.518428802490234,24.51805877685547,24.539533615112305,24.52960205078125,24.516101837158203,24.54224395751953,24.536623001098633,24.532499313354492,24.525978088378906,24.520153045654297,24.531070709228516,24.53160285949707,24.5384578704834,24.52641487121582,24.530345916748047,24.534257888793945,24.517770767211914,24.54834747314453,24.543912887573242,24.533430099487305,24.561676025390625,24.533920288085938,24.52506446838379,24.516429901123047,24.5318603515625,24.53031349182129,24.522293090820312,24.532257080078125,24.514171600341797,24.518177032470703,24.545654296875,24.511079788208008,24.505199432373047,24.511619567871094,24.517776489257812,24.513107299804688,24.510231018066406,24.510557174682617,24.512340545654297,24.513368606567383,24.517501831054688,24.513593673706055,24.513898849487305,24.512298583984375,24.512657165527344,24.51302146911621,24.512359619140625,24.510549545288086,24.518217086791992,24.50880241394043,24.51148223876953,24.508609771728516,24.50452423095703,24.51535415649414,24.507444381713867,24.505329132080078,24.5087833404541,24.501617431640625,24.50103187561035,24.49940299987793,24.498044967651367,24.498947143554688,24.49837875366211,24.495769500732422,24.500038146972656,24.496421813964844,24.4962215423584,24.494882583618164,24.496030807495117,24.49317169189453,24.4923095703125,24.489641189575195,24.49262237548828,24.491090774536133,24.4907283782959,24.49193000793457,24.490243911743164,24.489246368408203,24.489641189575195,24.4910945892334,24.490676879882812,24.490327835083008,24.494524002075195,24.493953704833984,24.49323272705078,24.494426727294922,24.494651794433594,24.496519088745117,24.498046875,24.497329711914062,24.496675491333008,24.49752426147461,24.497934341430664,24.498464584350586,24.49943733215332,24.498188018798828,24.499107360839844,24.49892807006836,24.502017974853516,24.501956939697266,24.502357482910156,24.502046585083008,24.502758026123047,24.50446128845215,24.504125595092773,24.504793167114258,24.503965377807617,24.503538131713867,24.50387191772461,24.50404167175293,24.503225326538086,24.502483367919922,24.503469467163086,24.503812789916992,24.503292083740234,24.503570556640625,24.504650115966797,24.504972457885742,24.505813598632812,24.506500244140625,24.506999969482422],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"#19D3F3","size":3},"mode":"markers","name":"cluster 5","x":[24.878137588500977,24.897722244262695,24.912324905395508,24.915855407714844,24.933372497558594,24.787015914916992,24.70752716064453,24.764280319213867,24.91604995727539,24.95610237121582,24.799800872802734,24.915363311767578,24.91368865966797,24.805068969726562,24.76215171813965,24.85344696044922,24.825408935546875,24.853778839111328,24.969694137573242,24.783117294311523,24.763853073120117,24.896360397338867,24.976762771606445,24.95639991760254,24.971330642700195,24.981292724609375,24.859416961669922,24.787033081054688,24.830848693847656,24.825286865234375,24.88829231262207,24.81566619873047,24.946714401245117,24.94023895263672,24.884748458862305,24.876981735229492,24.908557891845703,24.797019958496094,24.882099151611328,24.864173889160156,24.928600311279297,24.85321044921875,24.92643165588379,24.877103805541992,24.99156951904297,24.940872192382812,24.881208419799805,24.846139907836914,24.901470184326172,24.878725051879883,24.92527198791504,24.848064422607422,24.821147918701172,24.863935470581055,24.89904022216797,24.923566818237305,24.894023895263672,24.85995864868164,24.7769718170166,24.800304412841797,24.878408432006836,24.86937713623047,24.835121154785156,24.965299606323242,24.844318389892578,24.880718231201172,24.857032775878906,24.90164566040039,24.907297134399414,24.913331985473633,24.868404388427734,24.843732833862305,24.879220962524414,24.918792724609375,24.919063568115234,24.92487907409668,24.876245498657227,24.865888595581055,24.873287200927734,24.861040115356445,24.841032028198242,24.942352294921875,24.924869537353516,24.84207534790039,24.90145492553711,24.88174057006836,24.863719940185547,24.858985900878906,24.854019165039062,24.90818214416504,24.8963680267334,24.845443725585938,24.8479061126709,24.850662231445312,24.86467170715332,24.833450317382812,24.823593139648438,24.849287033081055,24.873598098754883,24.89006805419922,24.889955520629883,24.863929748535156,24.9260311126709,24.880016326904297,24.89227867126465,24.864484786987305,24.897483825683594,24.913162231445312,24.86512565612793,24.888500213623047,24.91380500793457,24.895450592041016,24.907726287841797,24.90322494506836,24.891529083251953,24.88294792175293,24.8846492767334,24.843353271484375,24.871604919433594,24.863000869750977,24.870159149169922,24.892417907714844,24.89850616455078,24.902889251708984,24.891807556152344,24.88818359375,24.887264251708984,24.901134490966797,24.893369674682617,24.90142250061035,24.90749168395996,24.881614685058594,24.886497497558594,24.83595848083496,24.869848251342773,24.899564743041992,24.8839054107666,24.899810791015625,24.898656845092773,24.90240478515625,24.9329833984375,24.895427703857422,24.89600944519043,24.87034034729004,24.892066955566406,24.90597152709961,24.885011672973633,24.88194465637207,24.891101837158203,24.900686264038086,24.876937866210938,24.879444122314453,24.866405487060547,24.87714195251465,24.87626075744629,24.876131057739258,24.86460304260254,24.873979568481445,24.875442504882812,24.869850158691406,24.87670135498047,24.867868423461914,24.864871978759766,24.876840591430664,24.869035720825195,24.850074768066406,24.875150680541992,24.872844696044922,24.874032974243164,24.875770568847656,24.860742568969727,24.86125946044922,24.869319915771484,24.857038497924805,24.8580379486084,24.868492126464844,24.85700035095215,24.876623153686523,24.874950408935547,24.87346076965332,24.861400604248047,24.86867904663086,24.86931610107422,24.88166618347168,24.866710662841797,24.868947982788086,24.858793258666992,24.836305618286133,24.87798500061035,24.859933853149414,24.867429733276367,24.86887550354004,24.871976852416992,24.862895965576172,24.8610782623291,24.863582611083984,24.86393928527832,24.834627151489258,24.862651824951172,24.865734100341797,24.870349884033203,24.86931800842285,24.867046356201172,24.865158081054688,24.86737823486328,24.86756706237793,24.869531631469727,24.873085021972656,24.8668270111084,24.872570037841797,24.866649627685547,24.876747131347656,24.875030517578125,24.876331329345703,24.876506805419922,24.875707626342773,24.88222885131836,24.869140625,24.875043869018555,24.8743839263916,24.87996482849121,24.877918243408203,24.877363204956055,24.876352310180664,24.877534866333008,24.874910354614258,24.883052825927734,24.871410369873047,24.87322998046875,24.871524810791016,24.869068145751953,24.870006561279297,24.86768341064453,24.86904525756836,24.871488571166992,24.875185012817383,24.87675666809082,24.868486404418945,24.869869232177734,24.87251091003418,24.87040901184082,24.87083625793457,24.871427536010742,24.871904373168945,24.870161056518555,24.871417999267578,24.87001609802246,24.87225914001465,24.87092399597168,24.87565803527832],"y":[3.6662564277648926,3.861542224884033,3.7608041763305664,3.6248855590820312,3.670372486114502,3.684420347213745,3.715815544128418,3.6940762996673584,3.6694416999816895,3.6678285598754883,3.731032371520996,3.7001214027404785,3.680007219314575,3.6643552780151367,3.8936069011688232,3.7605080604553223,3.6611835956573486,3.649562120437622,3.6709117889404297,3.707284688949585,3.678295850753784,3.586315631866455,3.644021511077881,3.7472288608551025,3.6071901321411133,3.5678982734680176,3.6444625854492188,3.742506980895996,3.785667896270752,3.6503827571868896,3.7013189792633057,3.6809134483337402,3.6576364040374756,3.6337735652923584,3.858027696609497,3.6076436042785645,3.688457489013672,3.7200775146484375,3.750617027282715,3.677177906036377,3.6585261821746826,3.6622538566589355,3.695348024368286,3.683610439300537,3.751927375793457,3.668245553970337,3.6844840049743652,3.6938869953155518,3.7128114700317383,3.7317733764648438,3.6504616737365723,3.711817502975464,3.725004196166992,3.7215659618377686,3.7008206844329834,3.7141616344451904,3.706516742706299,3.676184892654419,3.7163453102111816,3.718902587890625,3.7946102619171143,3.7286505699157715,3.7485995292663574,3.731842041015625,3.6778314113616943,3.6831722259521484,3.651534080505371,3.6346004009246826,3.6811466217041016,3.6478898525238037,3.6686019897460938,3.7338449954986572,3.715224504470825,3.6337435245513916,3.678950786590576,3.686258554458618,3.6973984241485596,3.715549945831299,3.685135841369629,3.7171225547790527,3.6883885860443115,3.7448906898498535,3.715730667114258,3.7243659496307373,3.7043089866638184,3.693739652633667,3.7014472484588623,3.7350823879241943,3.7229015827178955,3.7565417289733887,3.7199456691741943,3.7233543395996094,3.7041072845458984,3.749039649963379,3.722102403640747,3.72383713722229,3.7209513187408447,3.698289155960083,3.72493052482605,3.7205467224121094,3.7152397632598877,3.717489004135132,3.7246055603027344,3.7165307998657227,3.72186017036438,3.748884916305542,3.6957852840423584,3.715693950653076,3.7446229457855225,3.702829122543335,3.7066650390625,3.7064874172210693,3.740323305130005,3.7454943656921387,3.7194337844848633,3.731248140335083,3.7192559242248535,3.7433183193206787,3.7126553058624268,3.727959632873535,3.7280471324920654,3.718035936355591,3.7276360988616943,3.7178401947021484,3.7136621475219727,3.723642349243164,3.7288379669189453,3.7082014083862305,3.715428590774536,3.693164110183716,3.7305524349212646,3.725295305252075,3.723881244659424,3.741321325302124,3.7238306999206543,3.698528528213501,3.731738328933716,3.72515606880188,3.7184505462646484,3.71494197845459,3.739562749862671,3.71864652633667,3.7180685997009277,3.7435245513916016,3.7256524562835693,3.7351419925689697,3.7313661575317383,3.74189829826355,3.727795362472534,3.735028028488159,3.7214162349700928,3.727403163909912,3.723529577255249,3.721677303314209,3.7269155979156494,3.7270009517669678,3.7281134128570557,3.723175287246704,3.7254436016082764,3.730060577392578,3.7285046577453613,3.7275197505950928,3.721592426300049,3.7320780754089355,3.7317087650299072,3.741849660873413,3.7398180961608887,3.725470542907715,3.7339928150177,3.7310144901275635,3.739048957824707,3.7380409240722656,3.738330602645874,3.7384331226348877,3.744239568710327,3.7325103282928467,3.7375807762145996,3.7298636436462402,3.736710548400879,3.735161781311035,3.736370801925659,3.730311155319214,3.730402708053589,3.7373387813568115,3.7322909832000732,3.7320828437805176,3.734241485595703,3.8032124042510986,3.7292816638946533,3.732653856277466,3.7325470447540283,3.7344305515289307,3.7370405197143555,3.7377090454101562,3.727992534637451,3.7300822734832764,3.733161687850952,3.740999937057495,3.7334814071655273,3.729490041732788,3.729376792907715,3.732264757156372,3.7315948009490967,3.732813596725464,3.7332866191864014,3.7340569496154785,3.7317471504211426,3.7340288162231445,3.733985185623169,3.7311601638793945,3.7350950241088867,3.7333221435546875,3.733332395553589,3.733649253845215,3.7339794635772705,3.7358558177948,3.7438321113586426,3.7340381145477295,3.73226261138916,3.733902931213379,3.7325377464294434,3.73228120803833,3.7324821949005127,3.7324674129486084,3.7329108715057373,3.731750965118408,3.737433910369873,3.7289626598358154,3.7293612957000732,3.72786545753479,3.7266788482666016,3.727001667022705,3.7287933826446533,3.7284791469573975,3.72717022895813,3.7281060218811035,3.7267212867736816,3.7238407135009766,3.7215592861175537,3.720029354095459,3.7211451530456543,3.7216076850891113,3.720924139022827,3.7210440635681152,3.721468210220337,3.720813751220703,3.721019744873047,3.72066068649292,3.719758987426758,3.7196526527404785],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"}]},{"data":[{"marker":{"color":"#636EFA","size":3},"mode":"markers","name":"cluster 0","x":[2.574629306793213,2.574946403503418,2.5748322010040283,2.5749754905700684,2.5752291679382324,2.575122833251953,2.575509548187256,2.5754599571228027,2.5755109786987305,2.575997829437256,2.5757312774658203,2.575810194015503,2.575727701187134,2.5758817195892334,2.5763933658599854,2.5769259929656982,2.5772573947906494,2.5773422718048096,2.577369213104248,2.5772805213928223,2.577496290206909,2.5778310298919678,2.577639102935791,2.577752113342285,2.5777475833892822,2.5778489112854004,2.5779149532318115,2.578598737716675,2.5787062644958496,2.5785439014434814,2.578667163848877,2.5785887241363525,2.5787200927734375,2.57877779006958,2.578925609588623,2.5791614055633545,2.57928729057312,2.579463005065918,2.579444646835327,2.579587697982788,2.5797548294067383,2.5800788402557373,2.580014944076538,2.5800297260284424,2.5798325538635254,2.5798935890197754,2.579826831817627,2.5799386501312256,2.5798938274383545,2.579970359802246,2.5798709392547607,2.57987904548645,2.5799431800842285,2.579906702041626,2.5800631046295166,2.580024480819702,2.579991102218628,2.5801191329956055,2.580068826675415,2.580132484436035,2.5800793170928955,2.580165386199951,2.580277442932129,2.58029842376709,2.580247640609741,2.5801849365234375,2.5801291465759277,2.5801405906677246,2.580338954925537,2.5801913738250732,2.5801987648010254,2.580169916152954,2.5802183151245117,2.580171585083008,2.580066680908203,2.5799057483673096,2.5798585414886475,2.5798683166503906,2.579906702041626,2.57987380027771,2.579921245574951,2.5798943042755127,2.5799124240875244,2.579845905303955,2.5798680782318115,2.579941987991333,2.580003023147583,2.580061674118042,2.580012083053589,2.580057382583618,2.5800211429595947,2.5800061225891113,2.579996109008789,2.580000400543213,2.579955577850342,2.5801503658294678,2.5802249908447266,2.580254316329956,2.5803208351135254,2.580268621444702,2.5803463459014893,2.5804784297943115,2.580416679382324,2.5803627967834473,2.5803463459014893,2.5803165435791016,2.580341100692749,2.5803732872009277,2.580340623855591,2.5803658962249756,2.580348014831543,2.5803213119506836,2.5802319049835205,2.5801851749420166,2.580122232437134,2.580110549926758,2.5800862312316895,2.5801138877868652,2.5800933837890625,2.580077648162842,2.580047369003296,2.580030918121338,2.580002784729004,2.579963445663452,2.5798916816711426,2.57983136177063,2.579798936843872,2.5797367095947266,2.5796945095062256,2.579658269882202,2.579630136489868,2.579482316970825,2.579425573348999,2.5794293880462646,2.5793862342834473,2.5793347358703613,2.579268455505371,2.5792195796966553,2.5791709423065186,2.579115152359009,2.579002618789673,2.5789971351623535,2.5789546966552734,2.5789129734039307,2.5788650512695312,2.5788462162017822,2.5788164138793945,2.57877779006958,2.5787572860717773,2.578686237335205,2.578646421432495,2.57863450050354,2.5785984992980957,2.5785813331604004,2.57856822013855,2.578547954559326,2.5785326957702637,2.578533172607422,2.5785582065582275,2.5785562992095947,2.5785903930664062,2.5786097049713135,2.5785934925079346,2.5785651206970215,2.578562021255493,2.5785372257232666,2.578536033630371,2.5785019397735596,2.5784671306610107,2.5784380435943604,2.5784080028533936,2.578354835510254,2.578341484069824,2.578320264816284,2.5783164501190186,2.578259229660034,2.5782244205474854,2.5782253742218018,2.578235626220703,2.5782508850097656,2.578249216079712,2.578263521194458,2.578272581100464,2.5782904624938965,2.578295946121216,2.5782954692840576,2.578282594680786,2.5783064365386963,2.5783236026763916,2.5783159732818604,2.578317642211914,2.5783028602600098,2.5783159732818604,2.5783157348632812,2.5783166885375977,2.5783329010009766,2.5783376693725586,2.578320264816284,2.5783233642578125,2.5783157348632812,2.578317165374756,2.57832407951355,2.578324317932129,2.578242301940918,2.578237295150757,2.5782313346862793,2.5782277584075928,2.578211545944214,2.5782015323638916,2.5781972408294678,2.5781874656677246,2.578188180923462,2.5781900882720947,2.5781991481781006,2.5782063007354736,2.5782110691070557,2.5782175064086914,2.5782277584075928,2.5782337188720703,2.578258514404297,2.578272581100464,2.5782852172851562,2.5782864093780518,2.5782952308654785,2.578298568725586,2.578301429748535,2.5783019065856934,2.5783042907714844,2.5783090591430664,2.578324794769287,2.5783426761627197,2.578361749649048,2.578387975692749,2.5784120559692383,2.578437566757202,2.5784599781036377,2.5784876346588135,2.578517436981201,2.5785470008850098,2.578577756881714,2.5786070823669434,2.578641653060913,2.5786685943603516,2.578688859939575,2.578709840774536,2.5787339210510254,2.5787580013275146,2.5787875652313232,2.578817129135132,2.5788440704345703],"y":[-21.180849075317383,-21.18089485168457,-21.18065071105957,-21.18068504333496,-21.180540084838867,-21.180450439453125,-21.18038558959961,-21.1805419921875,-21.18069839477539,-21.180644989013672,-21.180559158325195,-21.180652618408203,-21.180519104003906,-21.18047332763672,-21.180416107177734,-21.180511474609375,-21.180320739746094,-21.1803035736084,-21.180654525756836,-21.180540084838867,-21.180452346801758,-21.180604934692383,-21.180444717407227,-21.18039894104004,-21.18041229248047,-21.18036651611328,-21.180309295654297,-21.180150985717773,-21.180248260498047,-21.180234909057617,-21.17998695373535,-21.17994499206543,-21.18002700805664,-21.180038452148438,-21.18011474609375,-21.17993927001953,-21.179885864257812,-21.180009841918945,-21.179990768432617,-21.17995262145996,-21.180009841918945,-21.18004035949707,-21.1800594329834,-21.17995834350586,-21.18007469177246,-21.180042266845703,-21.18012237548828,-21.18011474609375,-21.180221557617188,-21.180248260498047,-21.180095672607422,-21.180051803588867,-21.1800479888916,-21.180185317993164,-21.18025779724121,-21.18016242980957,-21.180002212524414,-21.179906845092773,-21.179845809936523,-21.17974281311035,-21.179719924926758,-21.179719924926758,-21.179668426513672,-21.17961311340332,-21.17959213256836,-21.179492950439453,-21.179336547851562,-21.179182052612305,-21.179031372070312,-21.178834915161133,-21.178781509399414,-21.178611755371094,-21.178607940673828,-21.178516387939453,-21.178375244140625,-21.178287506103516,-21.17823028564453,-21.178133010864258,-21.178071975708008,-21.17795753479004,-21.17790412902832,-21.177804946899414,-21.177766799926758,-21.177709579467773,-21.177635192871094,-21.17755889892578,-21.177534103393555,-21.177488327026367,-21.177473068237305,-21.17739486694336,-21.177385330200195,-21.17732810974121,-21.177385330200195,-21.177383422851562,-21.177316665649414,-21.177202224731445,-21.17717170715332,-21.177148818969727,-21.177146911621094,-21.17708396911621,-21.177032470703125,-21.176986694335938,-21.176990509033203,-21.176982879638672,-21.176939010620117,-21.176870346069336,-21.176801681518555,-21.176620483398438,-21.176584243774414,-21.17652702331543,-21.176584243774414,-21.176576614379883,-21.17660140991211,-21.176639556884766,-21.176652908325195,-21.17665672302246,-21.176664352416992,-21.176679611206055,-21.176681518554688,-21.176725387573242,-21.176790237426758,-21.17683219909668,-21.176834106445312,-21.176916122436523,-21.176923751831055,-21.17692756652832,-21.176929473876953,-21.176923751831055,-21.17692756652832,-21.17690658569336,-21.176939010620117,-21.17714500427246,-21.177146911621094,-21.177127838134766,-21.177152633666992,-21.177146911621094,-21.17716407775879,-21.177200317382812,-21.17719078063965,-21.177186965942383,-21.177268981933594,-21.1772518157959,-21.177257537841797,-21.17725944519043,-21.177263259887695,-21.177278518676758,-21.177274703979492,-21.17725372314453,-21.177274703979492,-21.17727279663086,-21.1772518157959,-21.177244186401367,-21.177221298217773,-21.177228927612305,-21.17724609375,-21.177268981933594,-21.177282333374023,-21.17728614807129,-21.17729377746582,-21.177303314208984,-21.177316665649414,-21.177322387695312,-21.177331924438477,-21.177352905273438,-21.177349090576172,-21.1773681640625,-21.177366256713867,-21.177377700805664,-21.17737579345703,-21.17737579345703,-21.177392959594727,-21.177440643310547,-21.177440643310547,-21.177448272705078,-21.17745590209961,-21.17745590209961,-21.177499771118164,-21.17750358581543,-21.177526473999023,-21.177547454833984,-21.177597045898438,-21.177631378173828,-21.177669525146484,-21.177717208862305,-21.177734375,-21.177776336669922,-21.17783546447754,-21.177865982055664,-21.177900314331055,-21.17793083190918,-21.17795753479004,-21.178010940551758,-21.178035736083984,-21.178075790405273,-21.1781005859375,-21.178142547607422,-21.178190231323242,-21.17824935913086,-21.17828941345215,-21.1783390045166,-21.178361892700195,-21.178390502929688,-21.178417205810547,-21.17863655090332,-21.178647994995117,-21.17864990234375,-21.178665161132812,-21.17867088317871,-21.178688049316406,-21.178707122802734,-21.17872428894043,-21.17873191833496,-21.178743362426758,-21.178743362426758,-21.178743362426758,-21.178741455078125,-21.178749084472656,-21.17874526977539,-21.178743362426758,-21.17873764038086,-21.178735733032227,-21.17872428894043,-21.178707122802734,-21.178686141967773,-21.178667068481445,-21.178640365600586,-21.17862319946289,-21.178600311279297,-21.178577423095703,-21.178558349609375,-21.178539276123047,-21.178525924682617,-21.17850685119629,-21.178497314453125,-21.17848777770996,-21.178478240966797,-21.1784725189209,-21.178466796875,-21.178468704223633,-21.178464889526367,-21.178470611572266,-21.178466796875,-21.178462982177734,-21.1784610748291,-21.178457260131836,-21.178449630737305,-21.178438186645508,-21.17843246459961,-21.178424835205078,-21.17841148376465],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"#EF553B","size":3},"mode":"markers","name":"cluster 1","x":[11.042937278747559,11.042984008789062,11.042994499206543,11.042551040649414,11.043000221252441,11.042693138122559,11.042752265930176,11.042525291442871,11.04232406616211,11.042044639587402,11.041979789733887,11.041860580444336,11.041218757629395,11.04091739654541,11.039923667907715,11.040224075317383,11.04039478302002,11.040229797363281,11.039381980895996,11.039725303649902,11.039436340332031,11.038690567016602,11.038105964660645,11.037869453430176,11.037726402282715,11.03764533996582,11.037467002868652,11.037469863891602,11.037267684936523,11.036665916442871,11.036481857299805,11.036659240722656,11.036238670349121,11.035964965820312,11.03613567352295,11.035848617553711,11.035711288452148,11.0358247756958,11.035748481750488,11.035544395446777,11.035211563110352,11.03605842590332,11.03596019744873,11.036026000976562,11.035940170288086,11.035552978515625,11.035823822021484,11.035539627075195,11.036041259765625,11.033955574035645,11.033955574035645,11.034247398376465,11.034332275390625,11.03384017944336,11.033897399902344,11.033750534057617,11.03365707397461,11.033705711364746,11.033615112304688,11.033519744873047,11.033219337463379,11.032805442810059,11.032809257507324,11.032825469970703,11.03260612487793,11.032912254333496,11.032854080200195,11.032877922058105,11.03278923034668,11.03284740447998,11.032447814941406,11.032389640808105,11.032333374023438,11.03235912322998,11.032349586486816,11.032305717468262,11.032238006591797,11.032012939453125,11.032286643981934,11.031082153320312,11.031038284301758,11.031047821044922,11.031150817871094,11.03093433380127,11.030946731567383,11.030776023864746,11.030900955200195,11.030694007873535,11.030774116516113,11.031027793884277,11.031025886535645,11.03092098236084,11.030640602111816,11.030842781066895,11.030694007873535,11.030391693115234,11.030466079711914,11.03038501739502,11.030425071716309,11.03044319152832,11.030228614807129,11.030299186706543,11.030165672302246,11.030107498168945,11.0302152633667,11.030336380004883,11.03035831451416,11.030410766601562,11.030406951904297,11.03017807006836,11.03044319152832,11.030467987060547,11.030322074890137,11.030299186706543,11.030455589294434,11.030417442321777,11.030476570129395,11.030500411987305,11.030614852905273,11.030566215515137,11.030550003051758,11.030694961547852,11.030658721923828,11.030722618103027,11.030678749084473,11.030698776245117,11.030577659606934,11.030805587768555,11.030689239501953,11.030665397644043,11.03056526184082,11.03060245513916,11.030603408813477,11.03045654296875,11.030355453491211,11.0303373336792,11.030278205871582,11.030187606811523,11.030115127563477,11.030197143554688,11.030008316040039,11.030008316040039,11.029934883117676,11.02995491027832,11.029921531677246,11.029890060424805,11.029900550842285,11.029900550842285,11.029938697814941,11.029887199401855,11.029868125915527,11.029794692993164,11.029731750488281,11.029605865478516,11.0295991897583,11.029566764831543,11.029539108276367,11.029556274414062,11.029475212097168,11.02947998046875,11.029590606689453,11.029559135437012,11.029566764831543,11.029501914978027,11.029417991638184,11.029376029968262,11.029397964477539,11.029346466064453,11.029353141784668,11.029375076293945,11.029396057128906,11.029346466064453,11.029337882995605,11.02929401397705,11.029287338256836,11.029287338256836,11.029257774353027,11.029274940490723,11.029253959655762,11.029274940490723,11.029245376586914,11.029277801513672,11.029213905334473,11.029191017150879,11.029155731201172,11.029167175292969,11.029139518737793,11.029145240783691,11.029142379760742,11.029118537902832,11.029107093811035,11.029118537902832,11.029081344604492,11.029129981994629,11.029125213623047,11.029085159301758,11.029058456420898,11.029090881347656,11.029040336608887,11.028993606567383,11.028943061828613,11.028919219970703,11.028876304626465,11.028844833374023,11.028783798217773,11.02876091003418,11.02877426147461,11.023200035095215,11.032246589660645,11.03225040435791,11.032230377197266,11.032281875610352,11.032296180725098,11.032308578491211,11.03233814239502,11.032344818115234,11.032365798950195,11.032347679138184,11.03235912322998,11.032369613647461,11.03239631652832,11.032435417175293,11.032479286193848,11.032598495483398,11.032621383666992,11.032636642456055,11.032703399658203,11.032708168029785,11.03272533416748,11.032707214355469,11.032687187194824,11.032769203186035,11.032733917236328,11.032727241516113,11.032711029052734,11.03268051147461,11.03265380859375,11.03261947631836,11.03256893157959,11.032554626464844,11.032577514648438,11.032554626464844,11.032519340515137,11.032493591308594,11.032466888427734,11.032444953918457,11.032424926757812,11.032401084899902,11.032505989074707,11.032464027404785],"y":[10.843704223632812,10.84361743927002,10.843866348266602,10.843619346618652,10.843151092529297,10.843354225158691,10.842999458312988,10.843509674072266,10.843810081481934,10.843750953674316,10.843100547790527,10.843061447143555,10.842757225036621,10.842581748962402,10.843093872070312,10.842838287353516,10.842852592468262,10.842909812927246,10.843104362487793,10.84241008758545,10.842702865600586,10.843174934387207,10.842971801757812,10.843368530273438,10.842955589294434,10.842838287353516,10.842849731445312,10.84287166595459,10.84282112121582,10.843195915222168,10.84347915649414,10.84360408782959,10.843822479248047,10.844194412231445,10.843854904174805,10.843978881835938,10.844120025634766,10.843791961669922,10.84339714050293,10.843304634094238,10.843681335449219,10.843599319458008,10.843385696411133,10.843029975891113,10.843381881713867,10.843567848205566,10.843114852905273,10.843348503112793,10.842742919921875,10.843134880065918,10.843010902404785,10.842782974243164,10.842496871948242,10.843161582946777,10.84300708770752,10.843052864074707,10.84294605255127,10.842781066894531,10.842889785766602,10.842782020568848,10.843317985534668,10.843494415283203,10.843128204345703,10.843399047851562,10.843360900878906,10.843212127685547,10.843155860900879,10.843017578125,10.843000411987305,10.842844009399414,10.843271255493164,10.843071937561035,10.843104362487793,10.843052864074707,10.843088150024414,10.84318733215332,10.843358993530273,10.843300819396973,10.843116760253906,10.843605041503906,10.843622207641602,10.843626022338867,10.843865394592285,10.843710899353027,10.843546867370605,10.843542098999023,10.843560218811035,10.843379974365234,10.843459129333496,10.843611717224121,10.843446731567383,10.843499183654785,10.843690872192383,10.843533515930176,10.843381881713867,10.843562126159668,10.843374252319336,10.843474388122559,10.843324661254883,10.84322738647461,10.843372344970703,10.843347549438477,10.843437194824219,10.843530654907227,10.843565940856934,10.843586921691895,10.843724250793457,10.843615531921387,10.843721389770508,10.843963623046875,10.84389591217041,10.843842506408691,10.843971252441406,10.843949317932129,10.84379768371582,10.843762397766113,10.843591690063477,10.843706130981445,10.8436918258667,10.84371566772461,10.843794822692871,10.843779563903809,10.843798637390137,10.84381103515625,10.8438720703125,10.843844413757324,10.843974113464355,10.843908309936523,10.844098091125488,10.844059944152832,10.844120025634766,10.844114303588867,10.844164848327637,10.844437599182129,10.84459400177002,10.844541549682617,10.84457778930664,10.844667434692383,10.844732284545898,10.844696044921875,10.844862937927246,10.84492015838623,10.845026016235352,10.845100402832031,10.845130920410156,10.845197677612305,10.84521198272705,10.845221519470215,10.84528923034668,10.845355987548828,10.84536361694336,10.845459938049316,10.845492362976074,10.845551490783691,10.845515251159668,10.845526695251465,10.84559154510498,10.845545768737793,10.845654487609863,10.845684051513672,10.845695495605469,10.845742225646973,10.8457670211792,10.845830917358398,10.845829963684082,10.845906257629395,10.845931053161621,10.846010208129883,10.846033096313477,10.846054077148438,10.846129417419434,10.846179962158203,10.84620475769043,10.84627628326416,10.846303939819336,10.84632682800293,10.846346855163574,10.84635066986084,10.84636116027832,10.846389770507812,10.846442222595215,10.846454620361328,10.846508026123047,10.846550941467285,10.846601486206055,10.846607208251953,10.846654891967773,10.846699714660645,10.846759796142578,10.84681510925293,10.84686279296875,10.846927642822266,10.8469877243042,10.847003936767578,10.847060203552246,10.847140312194824,10.847198486328125,10.847270011901855,10.847350120544434,10.847390174865723,10.847472190856934,10.847532272338867,10.847617149353027,10.847709655761719,10.847806930541992,10.847884178161621,10.84796142578125,10.855737686157227,10.843196868896484,10.84322452545166,10.843263626098633,10.843301773071289,10.843341827392578,10.843385696411133,10.843422889709473,10.843467712402344,10.843500137329102,10.843545913696289,10.843592643737793,10.843646049499512,10.843673706054688,10.843700408935547,10.843714714050293,10.843733787536621,10.843761444091797,10.843791007995605,10.843806266784668,10.843832969665527,10.843852996826172,10.843884468078613,10.843923568725586,10.843998908996582,10.844032287597656,10.844051361083984,10.844084739685059,10.844121932983398,10.84415340423584,10.844208717346191,10.844236373901367,10.844249725341797,10.844249725341797,10.84426212310791,10.84428596496582,10.844290733337402,10.84429931640625,10.844310760498047,10.844320297241211,10.844326972961426,10.844313621520996,10.84432315826416],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"#00CC96","size":3},"mode":"markers","name":"cluster 2","x":[-18.72412872314453,-18.723247528076172,-18.723268508911133,-18.723064422607422,-18.723400115966797,-18.72386360168457,-18.72374725341797,-18.72374725341797,-18.724369049072266,-18.724679946899414,-18.724557876586914,-18.724655151367188,-18.724952697753906,-18.725217819213867,-18.725025177001953,-18.72524070739746,-18.7252254486084,-18.72527503967285,-18.725618362426758,-18.725963592529297,-18.72623634338379,-18.726274490356445,-18.726274490356445,-18.726093292236328,-18.72574234008789,-18.725778579711914,-18.725831985473633,-18.725934982299805,-18.72642707824707,-18.725828170776367,-18.72565460205078,-18.725872039794922,-18.72594451904297,-18.72592544555664,-18.725332260131836,-18.725505828857422,-18.725473403930664,-18.72556495666504,-18.725862503051758,-18.726089477539062,-18.72593116760254,-18.725662231445312,-18.725814819335938,-18.726011276245117,-18.726016998291016,-18.726154327392578,-18.72620964050293,-18.72610855102539,-18.726139068603516,-18.72594451904297,-18.725767135620117,-18.725740432739258,-18.725658416748047,-18.725717544555664,-18.725780487060547,-18.725488662719727,-18.725181579589844,-18.72507667541504,-18.724838256835938,-18.724794387817383,-18.724458694458008,-18.724010467529297,-18.7238826751709,-18.723651885986328,-18.72347068786621,-18.723325729370117,-18.72329330444336,-18.72332763671875,-18.723604202270508,-18.723705291748047,-18.72360610961914,-18.723478317260742,-18.72355079650879,-18.72344207763672,-18.72331428527832,-18.723289489746094,-18.72298812866211,-18.72234535217285,-18.7224178314209,-18.72234344482422,-18.722379684448242,-18.72268295288086,-18.722370147705078,-18.722375869750977,-18.722444534301758,-18.722301483154297,-18.722190856933594,-18.72221565246582,-18.72218894958496,-18.722261428833008,-18.722339630126953,-18.72228240966797,-18.722383499145508,-18.722341537475586,-18.722000122070312,-18.72189712524414,-18.7219181060791,-18.72203826904297,-18.72199821472168,-18.722084045410156,-18.72199821472168,-18.722030639648438,-18.72201919555664,-18.722017288208008,-18.721935272216797,-18.721969604492188,-18.722002029418945,-18.72213363647461,-18.722257614135742,-18.72222328186035,-18.722318649291992,-18.722314834594727,-18.722354888916016,-18.72209358215332,-18.722118377685547,-18.722190856933594,-18.722166061401367,-18.722152709960938,-18.722108840942383,-18.722135543823242,-18.722064971923828,-18.722015380859375,-18.722034454345703,-18.722015380859375,-18.721982955932617,-18.721986770629883,-18.722003936767578,-18.721921920776367,-18.721792221069336,-18.72176742553711,-18.721799850463867,-18.721832275390625,-18.72185707092285,-18.72184181213379,-18.72176742553711,-18.721778869628906,-18.72178840637207,-18.7217960357666,-18.721799850463867,-18.72185516357422,-18.721832275390625,-18.72182273864746,-18.721817016601562,-18.7218017578125,-18.72176742553711,-18.72178840637207,-18.72179412841797,-18.7217960357666,-18.721805572509766,-18.721803665161133,-18.72178840637207,-18.721805572509766,-18.721786499023438,-18.721776962280273,-18.721782684326172,-18.72176742553711,-18.72174072265625,-18.721721649169922,-18.721675872802734,-18.721660614013672,-18.721670150756836,-18.721670150756836,-18.721635818481445,-18.721580505371094,-18.72153663635254,-18.721481323242188,-18.721445083618164,-18.721460342407227,-18.721477508544922,-18.721479415893555,-18.721473693847656,-18.721471786499023,-18.721494674682617,-18.721538543701172,-18.721567153930664,-18.7215576171875,-18.72158432006836,-18.721601486206055,-18.721620559692383,-18.721647262573242,-18.721643447875977,-18.721660614013672,-18.721677780151367,-18.72168731689453,-18.721717834472656,-18.72174072265625,-18.72174072265625,-18.721784591674805,-18.721832275390625,-18.721881866455078,-18.72193717956543,-18.721969604492188,-18.722002029418945,-18.722030639648438,-18.72205924987793,-18.722097396850586,-18.72214126586914,-18.72216796875,-18.722200393676758,-18.72222900390625,-18.722246170043945,-18.722270965576172,-18.72230339050293,-18.72233009338379,-18.72236442565918,-18.722410202026367,-18.722444534301758,-18.722484588623047,-18.722536087036133,-18.722585678100586,-18.722606658935547,-18.722644805908203,-18.722675323486328,-18.722692489624023,-18.722700119018555,-18.72271728515625,-18.722715377807617,-18.722721099853516,-18.722732543945312,-18.72273826599121,-18.722747802734375,-18.72275733947754,-18.722766876220703,-18.722780227661133,-18.72279930114746,-18.722822189331055,-18.72284507751465,-18.722856521606445,-18.72287940979004,-18.722902297973633,-18.722929000854492,-18.72295379638672,-18.72296905517578,-18.722978591918945,-18.722999572753906,-18.72301483154297,-18.723024368286133,-18.72304344177246,-18.72305679321289,-18.723060607910156,-18.723060607910156,-18.723060607910156,-18.723064422607422,-18.723060607910156,-18.723054885864258,-18.72304916381836,-18.723045349121094,-18.723039627075195,-18.72303581237793,-18.72303581237793],"y":[-5.473628044128418,-5.474231243133545,-5.47424840927124,-5.474493026733398,-5.4744462966918945,-5.47403621673584,-5.4741973876953125,-5.474318981170654,-5.474218368530273,-5.473567008972168,-5.4737114906311035,-5.473628997802734,-5.473325252532959,-5.47300910949707,-5.472995281219482,-5.473045349121094,-5.473178386688232,-5.473032474517822,-5.473175525665283,-5.473039627075195,-5.472844123840332,-5.472909450531006,-5.4728169441223145,-5.472947120666504,-5.473100662231445,-5.473147392272949,-5.473080158233643,-5.472963333129883,-5.472753524780273,-5.473146438598633,-5.473241806030273,-5.4732232093811035,-5.473299980163574,-5.473365783691406,-5.473812580108643,-5.4735517501831055,-5.473618507385254,-5.4737114906311035,-5.473465442657471,-5.473301410675049,-5.473522186279297,-5.473797798156738,-5.4738850593566895,-5.473795413970947,-5.473515033721924,-5.4735283851623535,-5.474222183227539,-5.474277973175049,-5.474243640899658,-5.474374771118164,-5.474282264709473,-5.474295139312744,-5.474497318267822,-5.474517822265625,-5.474740028381348,-5.474827289581299,-5.475121021270752,-5.475106716156006,-5.475090980529785,-5.475224494934082,-5.475470542907715,-5.4756879806518555,-5.475929260253906,-5.475919723510742,-5.475931167602539,-5.476024150848389,-5.475924491882324,-5.475887298583984,-5.475980758666992,-5.476003170013428,-5.4760308265686035,-5.476253032684326,-5.476211071014404,-5.476292133331299,-5.476351261138916,-5.476330280303955,-5.476354122161865,-5.476510524749756,-5.4763970375061035,-5.476439476013184,-5.476256370544434,-5.475893020629883,-5.475671291351318,-5.475954532623291,-5.4760541915893555,-5.47619104385376,-5.476271629333496,-5.476449966430664,-5.47642707824707,-5.476425647735596,-5.476306438446045,-5.476291656494141,-5.476269245147705,-5.476229190826416,-5.476222991943359,-5.476233005523682,-5.476141929626465,-5.476009845733643,-5.476175785064697,-5.476034164428711,-5.476070880889893,-5.476089954376221,-5.476040840148926,-5.476192474365234,-5.476263999938965,-5.476205825805664,-5.47620964050293,-5.47616720199585,-5.4762139320373535,-5.476276874542236,-5.476194858551025,-5.476151943206787,-5.476104259490967,-5.476309776306152,-5.47629451751709,-5.4762420654296875,-5.476348400115967,-5.476395606994629,-5.4764509201049805,-5.476421356201172,-5.476500511169434,-5.476552963256836,-5.476627826690674,-5.476680755615234,-5.476700305938721,-5.476715564727783,-5.476691246032715,-5.476705074310303,-5.476780891418457,-5.476813316345215,-5.476858139038086,-5.476835250854492,-5.476812839508057,-5.47681188583374,-5.47686243057251,-5.476815700531006,-5.476839542388916,-5.476888656616211,-5.476867198944092,-5.476917266845703,-5.476938724517822,-5.476919174194336,-5.476923942565918,-5.476939678192139,-5.476984024047852,-5.476973533630371,-5.477021217346191,-5.4769744873046875,-5.476975917816162,-5.476971626281738,-5.476919651031494,-5.476894378662109,-5.47692346572876,-5.476939678192139,-5.476943016052246,-5.476968288421631,-5.477027416229248,-5.477029323577881,-5.477057933807373,-5.477097034454346,-5.477088451385498,-5.477050304412842,-5.477024078369141,-5.477076530456543,-5.4770188331604,-5.4770917892456055,-5.477114677429199,-5.477060317993164,-5.47700834274292,-5.476975917816162,-5.4769511222839355,-5.476899147033691,-5.4768266677856445,-5.47674560546875,-5.4766669273376465,-5.476652145385742,-5.476603984832764,-5.47658109664917,-5.476535320281982,-5.476473808288574,-5.47650671005249,-5.476457118988037,-5.476402282714844,-5.4763593673706055,-5.476277828216553,-5.476226329803467,-5.476213455200195,-5.476128578186035,-5.476052761077881,-5.475993633270264,-5.475952625274658,-5.475895404815674,-5.475817680358887,-5.4757609367370605,-5.475702285766602,-5.47562313079834,-5.475558757781982,-5.475527286529541,-5.475492000579834,-5.475471019744873,-5.475459098815918,-5.475435733795166,-5.47541618347168,-5.475404262542725,-5.4753828048706055,-5.475353240966797,-5.4753336906433105,-5.475314617156982,-5.475291728973389,-5.475239276885986,-5.475229263305664,-5.4752068519592285,-5.475200653076172,-5.475201606750488,-5.475209712982178,-5.475216865539551,-5.4752197265625,-5.475227355957031,-5.4752373695373535,-5.475254058837891,-5.475268363952637,-5.475282669067383,-5.475302219390869,-5.475318431854248,-5.475329399108887,-5.475337505340576,-5.475345134735107,-5.475357532501221,-5.47536563873291,-5.47537899017334,-5.475393772125244,-5.475405216217041,-5.475423336029053,-5.475449562072754,-5.475465297698975,-5.475479602813721,-5.475495338439941,-5.475510120391846,-5.475521087646484,-5.475527763366699,-5.475535869598389,-5.475533962249756,-5.475534439086914,-5.475539207458496,-5.475546360015869,-5.475553512573242,-5.475557327270508,-5.475563049316406,-5.475569248199463,-5.475574493408203],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"#AB63FA","size":3},"mode":"markers","name":"cluster 3","x":[-20.59539031982422,-20.595577239990234,-20.595195770263672,-20.595335006713867,-20.595487594604492,-20.595579147338867,-20.59572982788086,-20.59569549560547,-20.59553337097168,-20.595474243164062,-20.595544815063477,-20.59547996520996,-20.595327377319336,-20.59519386291504,-20.59514617919922,-20.595218658447266,-20.595258712768555,-20.59514045715332,-20.595247268676758,-20.595399856567383,-20.595287322998047,-20.595287322998047,-20.595108032226562,-20.594768524169922,-20.59442138671875,-20.594295501708984,-20.594324111938477,-20.594335556030273,-20.594070434570312,-20.593896865844727,-20.593690872192383,-20.59393882751465,-20.593950271606445,-20.593814849853516,-20.59358024597168,-20.593568801879883,-20.593448638916016,-20.59332275390625,-20.593141555786133,-20.593338012695312,-20.593116760253906,-20.592987060546875,-20.592878341674805,-20.592775344848633,-20.59270477294922,-20.592744827270508,-20.592758178710938,-20.59272003173828,-20.592729568481445,-20.592771530151367,-20.592723846435547,-20.592693328857422,-20.592517852783203,-20.592575073242188,-20.592472076416016,-20.592254638671875,-20.59221076965332,-20.592134475708008,-20.591978073120117,-20.591899871826172,-20.59195327758789,-20.59188461303711,-20.591840744018555,-20.591630935668945,-20.591583251953125,-20.591503143310547,-20.59151268005371,-20.5915470123291,-20.591461181640625,-20.591398239135742,-20.591386795043945,-20.591524124145508,-20.591514587402344,-20.591659545898438,-20.5916805267334,-20.59161949157715,-20.591642379760742,-20.59151840209961,-20.591571807861328,-20.591581344604492,-20.591609954833984,-20.591625213623047,-20.591630935668945,-20.591711044311523,-20.59175682067871,-20.591796875,-20.591854095458984,-20.59180450439453,-20.591690063476562,-20.59157943725586,-20.59157371520996,-20.591690063476562,-20.591737747192383,-20.591724395751953,-20.591773986816406,-20.591806411743164,-20.59183120727539,-20.59184455871582,-20.59183692932129,-20.59185028076172,-20.591869354248047,-20.591936111450195,-20.591981887817383,-20.59210205078125,-20.592199325561523,-20.592235565185547,-20.592327117919922,-20.5924072265625,-20.592397689819336,-20.592449188232422,-20.592512130737305,-20.592559814453125,-20.59273910522461,-20.5927791595459,-20.592796325683594,-20.592838287353516,-20.592876434326172,-20.59288215637207,-20.592933654785156,-20.593008041381836,-20.59305763244629,-20.59313201904297,-20.593204498291016,-20.59327507019043,-20.593358993530273,-20.5933837890625,-20.59343147277832,-20.59351348876953,-20.593538284301758,-20.593568801879883,-20.59364891052246,-20.593698501586914,-20.593751907348633,-20.593782424926758,-20.593843460083008,-20.593843460083008,-20.593900680541992,-20.593929290771484,-20.5939884185791,-20.594058990478516,-20.59412384033203,-20.59417724609375,-20.59423065185547,-20.59431266784668,-20.594377517700195,-20.594470977783203,-20.594562530517578,-20.5946102142334,-20.59465217590332,-20.594680786132812,-20.59473419189453,-20.594816207885742,-20.594839096069336,-20.594871520996094,-20.594877243041992,-20.59490203857422,-20.59494400024414,-20.594953536987305,-20.5949764251709,-20.595001220703125,-20.595029830932617,-20.595060348510742,-20.595062255859375,-20.595083236694336,-20.595108032226562,-20.59516143798828,-20.59518814086914,-20.595197677612305,-20.595212936401367,-20.595224380493164,-20.595239639282227,-20.59526252746582,-20.595273971557617,-20.595264434814453,-20.595252990722656,-20.59524154663086,-20.595233917236328,-20.595224380493164,-20.5952091217041,-20.59518051147461,-20.595165252685547,-20.595155715942383,-20.59514045715332,-20.595123291015625,-20.59510040283203,-20.595077514648438,-20.59505844116211,-20.595041275024414,-20.59502601623535,-20.595014572143555,-20.59500503540039,-20.594993591308594,-20.594985961914062,-20.594980239868164,-20.594970703125,-20.594955444335938,-20.594932556152344,-20.594907760620117,-20.594894409179688,-20.594863891601562,-20.594839096069336,-20.594812393188477,-20.59478187561035,-20.594749450683594,-20.594715118408203,-20.59468650817871,-20.59465217590332,-20.59462547302246,-20.5945987701416,-20.59456443786621,-20.594533920288086,-20.594501495361328,-20.59446907043457,-20.594436645507812,-20.594404220581055,-20.594369888305664,-20.59433364868164,-20.594303131103516,-20.594276428222656,-20.59425163269043,-20.594223022460938,-20.594194412231445,-20.594161987304688,-20.594127655029297,-20.594087600708008,-20.594066619873047,-20.59404754638672,-20.594026565551758,-20.59400749206543,-20.593994140625,-20.593982696533203,-20.593971252441406,-20.59395980834961,-20.59394645690918,-20.59393882751465,-20.593923568725586,-20.59390640258789,-20.59389305114746,-20.5938777923584,-20.593860626220703,-20.593847274780273,-20.593835830688477,-20.593820571899414,-20.59380531311035,-20.59379768371582,-20.593788146972656,-20.59377670288086,-20.593765258789062,-20.59376335144043,-20.5937557220459],"y":[9.100902557373047,9.101497650146484,9.101789474487305,9.101836204528809,9.102006912231445,9.101701736450195,9.102226257324219,9.101954460144043,9.102029800415039,9.10201358795166,9.101914405822754,9.10179328918457,9.101729393005371,9.102197647094727,9.102307319641113,9.102411270141602,9.10273551940918,9.10330581665039,9.103551864624023,9.103547096252441,9.103572845458984,9.103568077087402,9.103726387023926,9.103896141052246,9.103487014770508,9.103816986083984,9.103869438171387,9.103691101074219,9.103647232055664,9.103536605834961,9.103759765625,9.10400390625,9.104045867919922,9.103928565979004,9.103567123413086,9.10317611694336,9.103171348571777,9.103009223937988,9.1027193069458,9.10274600982666,9.102944374084473,9.102804183959961,9.102831840515137,9.102782249450684,9.102575302124023,9.102466583251953,9.102356910705566,9.102068901062012,9.102044105529785,9.101926803588867,9.101765632629395,9.101614952087402,9.10139274597168,9.1011381149292,9.101126670837402,9.100872039794922,9.100761413574219,9.10063648223877,9.100537300109863,9.100665092468262,9.100737571716309,9.10068130493164,9.100618362426758,9.100276947021484,9.100358009338379,9.100130081176758,9.099943161010742,9.09993839263916,9.099928855895996,9.099852561950684,9.100091934204102,9.100163459777832,9.100014686584473,9.099944114685059,9.099873542785645,9.099851608276367,9.099760055541992,9.09953498840332,9.09946060180664,9.099349021911621,9.099248886108398,9.099089622497559,9.098943710327148,9.098806381225586,9.098894119262695,9.0989408493042,9.098732948303223,9.0987548828125,9.0986328125,9.098816871643066,9.098893165588379,9.098825454711914,9.098710060119629,9.098665237426758,9.098673820495605,9.098687171936035,9.098600387573242,9.098548889160156,9.098543167114258,9.098529815673828,9.098615646362305,9.098674774169922,9.098613739013672,9.098631858825684,9.0986328125,9.098586082458496,9.098609924316406,9.098695755004883,9.098529815673828,9.098542213439941,9.098649978637695,9.098681449890137,9.09884262084961,9.098820686340332,9.098814964294434,9.098814964294434,9.098736763000488,9.098634719848633,9.098579406738281,9.098620414733887,9.098633766174316,9.098763465881348,9.098730087280273,9.098587036132812,9.098575592041016,9.098577499389648,9.098536491394043,9.098636627197266,9.098616600036621,9.098625183105469,9.098677635192871,9.09864616394043,9.098687171936035,9.098859786987305,9.098908424377441,9.09881591796875,9.098731994628906,9.098698616027832,9.098701477050781,9.098712921142578,9.098735809326172,9.098723411560059,9.098719596862793,9.098703384399414,9.098677635192871,9.098749160766602,9.098750114440918,9.098737716674805,9.098787307739258,9.098760604858398,9.098773002624512,9.098761558532715,9.098766326904297,9.098803520202637,9.098775863647461,9.098776817321777,9.098769187927246,9.09878158569336,9.098790168762207,9.098790168762207,9.098824501037598,9.098832130432129,9.098820686340332,9.098834991455078,9.098858833312988,9.098960876464844,9.099003791809082,9.099047660827637,9.09904956817627,9.099061012268066,9.099050521850586,9.099090576171875,9.099112510681152,9.099138259887695,9.099156379699707,9.099177360534668,9.099209785461426,9.0992431640625,9.099282264709473,9.099318504333496,9.099323272705078,9.099353790283203,9.099358558654785,9.099376678466797,9.099380493164062,9.099390029907227,9.099418640136719,9.099446296691895,9.099477767944336,9.099502563476562,9.099522590637207,9.099535942077637,9.099555969238281,9.099588394165039,9.099603652954102,9.099621772766113,9.099635124206543,9.099665641784668,9.099691390991211,9.099705696105957,9.09973430633545,9.09975814819336,9.099782943725586,9.099804878234863,9.099831581115723,9.099852561950684,9.099881172180176,9.099906921386719,9.09992504119873,9.099950790405273,9.09997844696045,9.099996566772461,9.100003242492676,9.100011825561523,9.100025177001953,9.100042343139648,9.100045204162598,9.100054740905762,9.100067138671875,9.100078582763672,9.100089073181152,9.100103378295898,9.100113868713379,9.10012435913086,9.100129127502441,9.100128173828125,9.100129127502441,9.10013198852539,9.100140571594238,9.100143432617188,9.100149154663086,9.100153923034668,9.100153923034668,9.100156784057617,9.100156784057617,9.100152969360352,9.100146293640137,9.100136756896973,9.100130081176758,9.100120544433594,9.100113868713379,9.100110054016113,9.100107192993164,9.100099563598633,9.100093841552734,9.100089073181152,9.100085258483887,9.100077629089355,9.100080490112305,9.100083351135254],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"#FFA15A","size":3},"mode":"markers","name":"cluster 4","x":[-9.635234832763672,-9.635300636291504,-9.634973526000977,-9.634658813476562,-9.634596824645996,-9.634618759155273,-9.634361267089844,-9.634871482849121,-9.634849548339844,-9.634705543518066,-9.634992599487305,-9.634542465209961,-9.634657859802246,-9.63449764251709,-9.634530067443848,-9.634418487548828,-9.634119987487793,-9.6343412399292,-9.634081840515137,-9.633682250976562,-9.633788108825684,-9.633695602416992,-9.63360595703125,-9.63365650177002,-9.633533477783203,-9.633655548095703,-9.63356876373291,-9.633172035217285,-9.632617950439453,-9.632650375366211,-9.632831573486328,-9.633222579956055,-9.63318920135498,-9.63330078125,-9.633346557617188,-9.633411407470703,-9.63330364227295,-9.633468627929688,-9.633350372314453,-9.633553504943848,-9.633828163146973,-9.633843421936035,-9.633892059326172,-9.633932113647461,-9.633726119995117,-9.634102821350098,-9.633986473083496,-9.63403606414795,-9.634071350097656,-9.633981704711914,-9.633779525756836,-9.633721351623535,-9.633829116821289,-9.633578300476074,-9.633450508117676,-9.633508682250977,-9.633583068847656,-9.63353157043457,-9.633576393127441,-9.633590698242188,-9.633647918701172,-9.633456230163574,-9.633427619934082,-9.633392333984375,-9.633296966552734,-9.633285522460938,-9.633347511291504,-9.633252143859863,-9.633167266845703,-9.633278846740723,-9.63338565826416,-9.633415222167969,-9.633416175842285,-9.633495330810547,-9.633569717407227,-9.633699417114258,-9.633695602416992,-9.633675575256348,-9.633539199829102,-9.633041381835938,-9.633075714111328,-9.63314437866211,-9.633158683776855,-9.633200645446777,-9.63322925567627,-9.633213996887207,-9.633026123046875,-9.632789611816406,-9.632848739624023,-9.632828712463379,-9.632892608642578,-9.632944107055664,-9.632933616638184,-9.632966995239258,-9.632987976074219,-9.633049964904785,-9.633152961730957,-9.633269309997559,-9.63334846496582,-9.633437156677246,-9.633474349975586,-9.6334867477417,-9.633471488952637,-9.633520126342773,-9.63362979888916,-9.633655548095703,-9.633716583251953,-9.63381290435791,-9.633853912353516,-9.633883476257324,-9.633883476257324,-9.63382625579834,-9.63386058807373,-9.633913040161133,-9.63388729095459,-9.633906364440918,-9.633903503417969,-9.633909225463867,-9.633870124816895,-9.633830070495605,-9.633804321289062,-9.633805274963379,-9.633798599243164,-9.633819580078125,-9.633833885192871,-9.633822441101074,-9.633820533752441,-9.633831024169922,-9.633831977844238,-9.633844375610352,-9.63386344909668,-9.633843421936035,-9.633898735046387,-9.633907318115234,-9.63393497467041,-9.633959770202637,-9.634010314941406,-9.634060859680176,-9.634106636047363,-9.634105682373047,-9.634146690368652,-9.634198188781738,-9.634248733520508,-9.634303092956543,-9.634383201599121,-9.634421348571777,-9.63444995880127,-9.634521484375,-9.634559631347656,-9.634601593017578,-9.634678840637207,-9.634758949279785,-9.63481616973877,-9.634857177734375,-9.634912490844727,-9.634953498840332,-9.635004043579102,-9.635028839111328,-9.635034561157227,-9.635052680969238,-9.63510799407959,-9.635120391845703,-9.635133743286133,-9.635146141052246,-9.635149955749512,-9.635126113891602,-9.635119438171387,-9.635130882263184,-9.635139465332031,-9.635125160217285,-9.63511848449707,-9.635125160217285,-9.635123252868652,-9.635126113891602,-9.635132789611816,-9.635148048400879,-9.635150909423828,-9.63516902923584,-9.635172843933105,-9.635156631469727,-9.635146141052246,-9.635137557983398,-9.635124206542969,-9.635110855102539,-9.63509750366211,-9.635080337524414,-9.635079383850098,-9.63508129119873,-9.635072708129883,-9.635076522827148,-9.635082244873047,-9.635085105895996,-9.635090827941895,-9.635096549987793,-9.635096549987793,-9.635098457336426,-9.63509750366211,-9.635102272033691,-9.63509464263916,-9.635076522827148,-9.635072708129883,-9.635063171386719,-9.635051727294922,-9.635028839111328,-9.635003089904785,-9.634978294372559,-9.6349458694458,-9.634918212890625,-9.634886741638184,-9.634848594665527,-9.63481616973877,-9.63478946685791,-9.634766578674316,-9.634748458862305,-9.634727478027344,-9.634708404541016,-9.634687423706055,-9.634671211242676,-9.634651184082031,-9.634635925292969,-9.63461971282959,-9.634605407714844,-9.634588241577148,-9.634571075439453,-9.634552955627441,-9.634532928466797,-9.634514808654785,-9.63449764251709,-9.634482383728027,-9.634464263916016,-9.63444995880127,-9.634435653686523,-9.634419441223145,-9.634401321411133,-9.634389877319336,-9.634367942810059,-9.634343147277832,-9.634322166442871,-9.634298324584961,-9.63428020477295,-9.634262084960938,-9.634243965148926,-9.634234428405762,-9.634222984313965,-9.634212493896484,-9.634204864501953,-9.634201049804688,-9.634194374084473,-9.634187698364258,-9.63418197631836],"y":[24.5078067779541,24.50800895690918,24.508012771606445,24.507919311523438,24.507688522338867,24.508054733276367,24.507659912109375,24.50783920288086,24.50787925720215,24.507661819458008,24.507341384887695,24.507143020629883,24.507081985473633,24.507343292236328,24.50730323791504,24.507286071777344,24.507394790649414,24.506954193115234,24.506832122802734,24.507482528686523,24.507307052612305,24.507368087768555,24.507251739501953,24.507217407226562,24.507179260253906,24.506967544555664,24.50689697265625,24.507001876831055,24.507041931152344,24.506887435913086,24.507205963134766,24.506650924682617,24.506671905517578,24.506677627563477,24.506710052490234,24.507047653198242,24.506887435913086,24.506860733032227,24.50695037841797,24.50730323791504,24.507070541381836,24.507396697998047,24.507726669311523,24.507606506347656,24.507644653320312,24.507732391357422,24.507780075073242,24.507444381713867,24.50758934020996,24.507709503173828,24.507535934448242,24.507524490356445,24.507244110107422,24.507585525512695,24.507511138916016,24.507417678833008,24.50771141052246,24.50753402709961,24.507652282714844,24.507591247558594,24.507381439208984,24.507415771484375,24.507266998291016,24.50726890563965,24.50724220275879,24.507389068603516,24.507476806640625,24.507366180419922,24.50743293762207,24.507667541503906,24.507659912109375,24.50746726989746,24.507278442382812,24.50731658935547,24.507226943969727,24.507564544677734,24.5078125,24.50785255432129,24.5080509185791,24.508272171020508,24.508337020874023,24.50809097290039,24.508073806762695,24.508094787597656,24.508193969726562,24.508272171020508,24.50838279724121,24.508533477783203,24.508403778076172,24.508602142333984,24.50870704650879,24.508636474609375,24.5085506439209,24.508604049682617,24.50855255126953,24.508556365966797,24.508501052856445,24.508581161499023,24.508563995361328,24.50864601135254,24.508615493774414,24.508541107177734,24.508567810058594,24.508621215820312,24.50869369506836,24.5086669921875,24.508886337280273,24.50895118713379,24.508947372436523,24.508914947509766,24.508922576904297,24.508930206298828,24.508874893188477,24.508834838867188,24.50883674621582,24.508779525756836,24.508758544921875,24.508813858032227,24.508790969848633,24.508893966674805,24.50889015197754,24.508831024169922,24.50884246826172,24.508758544921875,24.508676528930664,24.50860595703125,24.50859260559082,24.50857925415039,24.508590698242188,24.50863265991211,24.50859832763672,24.50855827331543,24.50843620300293,24.508352279663086,24.508317947387695,24.508180618286133,24.508068084716797,24.507970809936523,24.507902145385742,24.507850646972656,24.50775909423828,24.507661819458008,24.507539749145508,24.507463455200195,24.507373809814453,24.50726318359375,24.50722312927246,24.507057189941406,24.50691032409668,24.506803512573242,24.506587982177734,24.5064754486084,24.50640106201172,24.50636100769043,24.50625991821289,24.506160736083984,24.5060977935791,24.505992889404297,24.505958557128906,24.50591278076172,24.505756378173828,24.505733489990234,24.505733489990234,24.50571060180664,24.50566291809082,24.505630493164062,24.505615234375,24.505596160888672,24.50556755065918,24.505537033081055,24.50548553466797,24.505456924438477,24.505420684814453,24.50539779663086,24.5053653717041,24.505338668823242,24.505308151245117,24.505285263061523,24.505229949951172,24.505218505859375,24.50519561767578,24.50518035888672,24.50518226623535,24.505144119262695,24.50513458251953,24.50513458251953,24.505117416381836,24.50513458251953,24.50514793395996,24.505172729492188,24.505197525024414,24.505226135253906,24.505252838134766,24.50528907775879,24.50531005859375,24.505346298217773,24.50538444519043,24.50542640686035,24.505464553833008,24.505512237548828,24.505565643310547,24.505630493164062,24.50568199157715,24.505741119384766,24.505802154541016,24.505857467651367,24.505916595458984,24.505983352661133,24.50605010986328,24.5061092376709,24.50617027282715,24.5062313079834,24.50627899169922,24.506328582763672,24.50638198852539,24.50642967224121,24.50647735595703,24.506519317626953,24.506549835205078,24.506587982177734,24.506624221801758,24.506662368774414,24.50670051574707,24.50673484802246,24.506763458251953,24.506797790527344,24.50682830810547,24.506855010986328,24.506877899169922,24.50689697265625,24.506914138793945,24.50693702697754,24.50695037841797,24.506961822509766,24.506973266601562,24.506980895996094,24.506994247436523,24.507009506225586,24.50701904296875,24.507028579711914,24.507049560546875,24.507062911987305,24.507078170776367,24.50709342956543,24.507110595703125,24.507122039794922,24.50713348388672,24.507143020629883,24.50714683532715,24.507150650024414],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"#19D3F3","size":3},"mode":"markers","name":"cluster 5","x":[24.875978469848633,24.875965118408203,24.875883102416992,24.875749588012695,24.87558937072754,24.87532615661621,24.87566375732422,24.8763484954834,24.8768253326416,24.876672744750977,24.87632942199707,24.87665367126465,24.87649917602539,24.876333236694336,24.87660026550293,24.877079010009766,24.877172470092773,24.877384185791016,24.877492904663086,24.877098083496094,24.877473831176758,24.877948760986328,24.877883911132812,24.877483367919922,24.877174377441406,24.87679672241211,24.876365661621094,24.876422882080078,24.87678337097168,24.876970291137695,24.877180099487305,24.877132415771484,24.87738800048828,24.877111434936523,24.876850128173828,24.87681770324707,24.876819610595703,24.876686096191406,24.877012252807617,24.876991271972656,24.87704849243164,24.876832962036133,24.876934051513672,24.87673568725586,24.876739501953125,24.87627601623535,24.87601089477539,24.875991821289062,24.876115798950195,24.876005172729492,24.87600326538086,24.87579917907715,24.87590789794922,24.876131057739258,24.87618064880371,24.8760929107666,24.875900268554688,24.875825881958008,24.875885009765625,24.87628173828125,24.876585006713867,24.87657928466797,24.87660789489746,24.876779556274414,24.876422882080078,24.876556396484375,24.876537322998047,24.87661361694336,24.876516342163086,24.876394271850586,24.876245498657227,24.876272201538086,24.87640380859375,24.876394271850586,24.876224517822266,24.87605094909668,24.875856399536133,24.875856399536133,24.875896453857422,24.875904083251953,24.87596321105957,24.87610626220703,24.87584114074707,24.875642776489258,24.875776290893555,24.87567710876465,24.87565040588379,24.875694274902344,24.875764846801758,24.875856399536133,24.875728607177734,24.875642776489258,24.875762939453125,24.875873565673828,24.875972747802734,24.876020431518555,24.876190185546875,24.87639808654785,24.876508712768555,24.876522064208984,24.876466751098633,24.876413345336914,24.8764591217041,24.876264572143555,24.876249313354492,24.876184463500977,24.876232147216797,24.87614631652832,24.87599754333496,24.87604331970215,24.875993728637695,24.875843048095703,24.875762939453125,24.875635147094727,24.875524520874023,24.875459671020508,24.875431060791016,24.875394821166992,24.875520706176758,24.875537872314453,24.875587463378906,24.875608444213867,24.875545501708984,24.875450134277344,24.875337600708008,24.875274658203125,24.875225067138672,24.875173568725586,24.875070571899414,24.875,24.87489128112793,24.8747615814209,24.874732971191406,24.874685287475586,24.874841690063477,24.874862670898438,24.8747615814209,24.874727249145508,24.8746280670166,24.874530792236328,24.874420166015625,24.874183654785156,24.874101638793945,24.874008178710938,24.8740234375,24.873950958251953,24.87382698059082,24.873781204223633,24.873750686645508,24.87367820739746,24.873571395874023,24.87355613708496,24.87353515625,24.87356185913086,24.873544692993164,24.873537063598633,24.87352752685547,24.873563766479492,24.87356185913086,24.873552322387695,24.873567581176758,24.873554229736328,24.873577117919922,24.873611450195312,24.87360191345215,24.873619079589844,24.87371253967285,24.87370491027832,24.87371253967285,24.87371063232422,24.873699188232422,24.87375259399414,24.873804092407227,24.873817443847656,24.873886108398438,24.873950958251953,24.87397575378418,24.874040603637695,24.87403106689453,24.874025344848633,24.8740291595459,24.874082565307617,24.874099731445312,24.874122619628906,24.87409019470215,24.87411880493164,24.8741397857666,24.874202728271484,24.874353408813477,24.874340057373047,24.87439727783203,24.874422073364258,24.87444496154785,24.874454498291016,24.874502182006836,24.874557495117188,24.87459945678711,24.87464141845703,24.874805450439453,24.874847412109375,24.874887466430664,24.87490463256836,24.874927520751953,24.87495994567871,24.875,24.875030517578125,24.87506103515625,24.87508201599121,24.87508773803711,24.875120162963867,24.875133514404297,24.875165939331055,24.875160217285156,24.87516212463379,24.875158309936523,24.875152587890625,24.875150680541992,24.8751220703125,24.87514305114746,24.87514305114746,24.875146865844727,24.87512969970703,24.875118255615234,24.875106811523438,24.87510108947754,24.875091552734375,24.875093460083008,24.87506103515625,24.875078201293945,24.875085830688477,24.875097274780273,24.875120162963867,24.875146865844727,24.875173568725586,24.87519645690918,24.875213623046875,24.875213623046875,24.875207901000977,24.87523651123047,24.875253677368164,24.875263214111328,24.875288009643555,24.875301361083984,24.87531852722168,24.87533187866211,24.87535285949707,24.875368118286133,24.87538719177246,24.875402450561523,24.87541961669922],"y":[3.7174599170684814,3.717703342437744,3.717107057571411,3.716907262802124,3.717282295227051,3.717480182647705,3.717622756958008,3.717622995376587,3.7177042961120605,3.7178945541381836,3.7181146144866943,3.7180519104003906,3.7181198596954346,3.7182748317718506,3.7185332775115967,3.717805862426758,3.717621088027954,3.717844009399414,3.7181153297424316,3.7183172702789307,3.718358278274536,3.7184994220733643,3.7190332412719727,3.719348192214966,3.7192180156707764,3.7196617126464844,3.7202813625335693,3.7205965518951416,3.7205123901367188,3.720238208770752,3.7205212116241455,3.720597505569458,3.7207510471343994,3.721001625061035,3.7213714122772217,3.7208049297332764,3.7212629318237305,3.7213988304138184,3.721404790878296,3.721282958984375,3.721457004547119,3.721710205078125,3.7219491004943848,3.722055673599243,3.7222118377685547,3.72208833694458,3.7223052978515625,3.722458839416504,3.7225730419158936,3.7226128578186035,3.72257137298584,3.7228639125823975,3.722909450531006,3.722900152206421,3.7229042053222656,3.7229931354522705,3.7230279445648193,3.723093271255493,3.7232840061187744,3.72331166267395,3.7233309745788574,3.72304368019104,3.723022699356079,3.7229175567626953,3.7228810787200928,3.7230615615844727,3.723219633102417,3.7235047817230225,3.723862886428833,3.724032402038574,3.7243382930755615,3.724562883377075,3.724525213241577,3.724559783935547,3.724924087524414,3.7251086235046387,3.725264310836792,3.725376844406128,3.725414991378784,3.725576639175415,3.7256100177764893,3.725759267807007,3.725682497024536,3.7257232666015625,3.7257273197174072,3.725813865661621,3.7259418964385986,3.7260403633117676,3.7260043621063232,3.7260172367095947,3.7258949279785156,3.7259185314178467,3.725928544998169,3.7260162830352783,3.725923776626587,3.7259397506713867,3.725947856903076,3.7259669303894043,3.7260782718658447,3.7260828018188477,3.726104736328125,3.7261483669281006,3.726182222366333,3.726188898086548,3.7262279987335205,3.726245403289795,3.72615385055542,3.72627592086792,3.726318836212158,3.7262449264526367,3.7263383865356445,3.7264175415039062,3.726497173309326,3.726442337036133,3.726365566253662,3.726393699645996,3.7263741493225098,3.7264034748077393,3.726335048675537,3.7263903617858887,3.7263834476470947,3.726376533508301,3.7264106273651123,3.726405143737793,3.7264387607574463,3.7264907360076904,3.7265024185180664,3.726491928100586,3.7265658378601074,3.726609945297241,3.7267439365386963,3.726728677749634,3.7267346382141113,3.7267463207244873,3.7266879081726074,3.726698875427246,3.7268118858337402,3.726792097091675,3.7267985343933105,3.726832628250122,3.726879835128784,3.7268290519714355,3.7268614768981934,3.7268965244293213,3.726830005645752,3.726835012435913,3.7268013954162598,3.7267844676971436,3.7267231941223145,3.7267189025878906,3.7266855239868164,3.7267065048217773,3.7267041206359863,3.7267167568206787,3.726736307144165,3.726735830307007,3.7267348766326904,3.72672963142395,3.7267439365386963,3.7267489433288574,3.726735830307007,3.7267284393310547,3.7267251014709473,3.72674560546875,3.726724624633789,3.7267048358917236,3.7266438007354736,3.726590871810913,3.7265963554382324,3.7265665531158447,3.726548433303833,3.72649884223938,3.726452350616455,3.726404905319214,3.7263565063476562,3.726284980773926,3.726260185241699,3.72621488571167,3.726200580596924,3.7261581420898438,3.7261223793029785,3.726081609725952,3.726064682006836,3.7260472774505615,3.7260022163391113,3.7259769439697266,3.725952625274658,3.7259199619293213,3.7256104946136475,3.725595474243164,3.72556734085083,3.725539445877075,3.72550368309021,3.725457191467285,3.7254085540771484,3.725398540496826,3.725379467010498,3.725348472595215,3.7252860069274902,3.725252628326416,3.7252357006073,3.725219488143921,3.725191354751587,3.725165843963623,3.725135087966919,3.725102663040161,3.725066900253296,3.7250399589538574,3.725003957748413,3.7249679565429688,3.724943161010742,3.724903106689453,3.7248694896698,3.7248356342315674,3.724799871444702,3.7247633934020996,3.7247188091278076,3.724642753601074,3.724604368209839,3.724573850631714,3.724536895751953,3.7245051860809326,3.7244739532470703,3.7244417667388916,3.724409580230713,3.7243754863739014,3.72434663772583,3.7242934703826904,3.7242748737335205,3.724255084991455,3.724240303039551,3.7242305278778076,3.724220037460327,3.7242014408111572,3.7241837978363037,3.724172353744507,3.7241573333740234,3.724146604537964,3.7241475582122803,3.7241575717926025,3.7241740226745605,3.724186658859253,3.724196672439575,3.7242093086242676,3.724222183227539,3.724234104156494,3.7242472171783447,3.724259853363037,3.7242743968963623,3.724292516708374],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"}]},{"data":[{"marker":{"color":"#636EFA","size":3},"mode":"markers","name":"cluster 0","x":[2.578866720199585,2.578883409500122,2.5788991451263428,2.5789153575897217,2.5789308547973633,2.5789456367492676,2.5789613723754883,2.578975200653076,2.578989028930664,2.579003095626831,2.579015016555786,2.5790281295776367,2.5790412425994873,2.579054594039917,2.5790669918060303,2.5790772438049316,2.5790863037109375,2.5790934562683105,2.5791003704071045,2.5791072845458984,2.5791144371032715,2.5791213512420654,2.5791265964508057,2.579132556915283,2.5791380405426025,2.579143762588501,2.579148769378662,2.579153537750244,2.579155921936035,2.579157829284668,2.57915997505188,2.5791618824005127,2.5791642665863037,2.5791659355163574,2.5791678428649902,2.5791683197021484,2.5791683197021484,2.5791680812835693,2.579167127609253,2.5791656970977783,2.5791637897491455,2.5791618824005127,2.579158306121826,2.5791547298431396,2.579151153564453,2.579148292541504,2.5791451930999756,2.5791428089141846,2.579139471054077,2.579136610031128,2.5791332721710205,2.5791304111480713,2.579127311706543,2.5791239738464355,2.5791208744049072,2.5791170597076416,2.579113721847534,2.5791101455688477,2.579105854034424,2.579102039337158,2.5790979862213135,2.579094171524048,2.579089641571045,2.579085111618042,2.579080104827881,2.579075574874878,2.579071044921875,2.579066753387451,2.5790627002716064,2.579056978225708,2.579052448272705,2.579047679901123,2.579043388366699,2.5790388584136963,2.5790343284606934,2.5790302753448486,2.579026699066162,2.5790233612060547,2.5790202617645264,2.5790164470672607,2.5790131092071533,2.579009532928467,2.5790059566497803,2.5790023803710938,2.5789990425109863,2.5789954662323,2.578991651535034,2.5789875984191895,2.5789830684661865,2.578979015350342,2.578974723815918,2.578970432281494,2.5789663791656494,2.578962564468384,2.57895827293396,2.578953981399536,2.578949213027954,2.578944206237793,2.5789389610290527,2.5789334774017334,2.578927993774414,2.578922748565674,2.578916549682617,2.5789103507995605,2.578904390335083,2.5788986682891846,2.5788934230804443,2.578887462615967,2.57888126373291,2.5788755416870117,2.5788698196411133,2.5788638591766357,2.5788581371307373,2.578852653503418,2.5788474082946777,2.5788424015045166,2.5788369178771973,2.578831911087036,2.578826904296875,2.5788216590881348,2.5788164138793945,2.5788114070892334,2.5788066387176514,2.5788018703460693,2.5787973403930664,2.5787928104400635,2.5787887573242188,2.578784704208374,2.5787808895111084,2.5787770748138428,2.5787737369537354,2.578770399093628,2.5787675380706787,2.5787651538848877,2.5787625312805176,2.5787601470947266,2.5787577629089355,2.5787556171417236,2.578753709793091,2.578752040863037,2.5787506103515625,2.578749656677246,2.5787487030029297,2.5787479877471924,2.578747034072876,2.5787465572357178,2.5787460803985596,2.5787460803985596,2.5787460803985596,2.5787458419799805,2.5787460803985596,2.5787463188171387,2.578746795654297,2.578747272491455,2.5787479877471924,2.578748941421509,2.578749656677246,2.5787503719329834,2.5787513256073,2.578752040863037,2.5787527561187744,2.5787534713745117,2.57875394821167,2.5787546634674072,2.5787553787231445,2.578756093978882,2.5787572860717773,2.5787580013275146,2.578758955001831,2.5787601470947266,2.578761577606201,2.5787627696990967,2.5787644386291504,2.578766345977783,2.578768014907837,2.5787699222564697,2.5787720680236816,2.5787742137908936,2.5787763595581055,2.5787785053253174,2.5787806510925293,2.578782796859741,2.578784942626953,2.578787088394165,2.578788995742798,2.5787909030914307,2.5787928104400635,2.5787949562072754,2.578796863555908,2.578798770904541,2.578800678253174,2.5788025856018066,2.5788047313690186,2.5788066387176514,2.578808546066284,2.578810453414917,2.57881236076355,2.5788142681121826,2.5788164138793945,2.5788183212280273,2.57882022857666,2.578822135925293,2.578824281692505,2.5788261890411377,2.5788285732269287,2.5788309574127197,2.5788331031799316,2.5788354873657227,2.5788381099700928,2.578840732574463,2.578843593597412,2.578845739364624,2.5788486003875732,2.5788512229919434,2.5788538455963135,2.5788562297821045,2.5788590908050537,2.578861713409424,2.578864097595215,2.578866720199585,2.578869104385376,2.578871488571167,2.578873634338379,2.57887601852417,2.578878402709961,2.578880786895752,2.578883171081543,2.578885555267334,2.578887939453125,2.578890085220337,2.578892469406128,2.578894853591919,2.5788967609405518,2.5788986682891846,2.5789008140563965,2.5789027214050293,2.578904390335083,2.5789058208465576,2.5789074897766113,2.578908920288086,2.5789103507995605,2.578911304473877,2.5789124965667725,2.578913450241089,2.5789144039154053,2.5789151191711426,2.578916072845459,2.578916549682617,2.5789170265197754,2.5789175033569336],"y":[-21.17839813232422,-21.178390502929688,-21.17837905883789,-21.178367614746094,-21.17835807800293,-21.178348541259766,-21.178340911865234,-21.178335189819336,-21.178325653076172,-21.178316116333008,-21.178308486938477,-21.178298950195312,-21.17828941345215,-21.178281784057617,-21.178272247314453,-21.178258895874023,-21.178251266479492,-21.17824363708496,-21.17823600769043,-21.178226470947266,-21.1782169342041,-21.178207397460938,-21.178199768066406,-21.178190231323242,-21.178180694580078,-21.178173065185547,-21.178163528442383,-21.17815589904785,-21.178146362304688,-21.178138732910156,-21.178133010864258,-21.178123474121094,-21.178117752075195,-21.178110122680664,-21.1781005859375,-21.17809295654297,-21.178085327148438,-21.178077697753906,-21.178071975708008,-21.178062438964844,-21.17805290222168,-21.17804527282715,-21.17803955078125,-21.178028106689453,-21.178022384643555,-21.17801284790039,-21.178003311157227,-21.177997589111328,-21.177989959716797,-21.177980422973633,-21.1779727935791,-21.177963256835938,-21.177953720092773,-21.177946090698242,-21.17793846130371,-21.177928924560547,-21.177921295166016,-21.17791175842285,-21.177902221679688,-21.177894592285156,-21.177886962890625,-21.177879333496094,-21.177871704101562,-21.17786407470703,-21.1778564453125,-21.177854537963867,-21.177846908569336,-21.177841186523438,-21.177837371826172,-21.177824020385742,-21.17782211303711,-21.177818298339844,-21.17781639099121,-21.177812576293945,-21.177810668945312,-21.17780876159668,-21.177806854248047,-21.177806854248047,-21.17780303955078,-21.17780303955078,-21.17780303955078,-21.17780303955078,-21.17780303955078,-21.17780303955078,-21.17780113220215,-21.17780113220215,-21.17780303955078,-21.17780303955078,-21.177804946899414,-21.177804946899414,-21.17780876159668,-21.177810668945312,-21.177812576293945,-21.17781639099121,-21.17781639099121,-21.17781639099121,-21.177818298339844,-21.17782211303711,-21.177824020385742,-21.177825927734375,-21.17782974243164,-21.177837371826172,-21.177839279174805,-21.177841186523438,-21.177845001220703,-21.17784881591797,-21.177854537963867,-21.177858352661133,-21.1778621673584,-21.177867889404297,-21.177873611450195,-21.177879333496094,-21.177885055541992,-21.177888870239258,-21.177894592285156,-21.177900314331055,-21.17790412902832,-21.177907943725586,-21.177913665771484,-21.177919387817383,-21.177921295166016,-21.17792320251465,-21.177928924560547,-21.177932739257812,-21.17793846130371,-21.177942276000977,-21.177946090698242,-21.177949905395508,-21.177953720092773,-21.177959442138672,-21.177963256835938,-21.177968978881836,-21.17797088623047,-21.177976608276367,-21.177978515625,-21.177982330322266,-21.17798614501953,-21.177988052368164,-21.17799186706543,-21.177993774414062,-21.17799949645996,-21.178001403808594,-21.17800521850586,-21.178009033203125,-21.178009033203125,-21.17801284790039,-21.178016662597656,-21.17801856994629,-21.178022384643555,-21.178024291992188,-21.178028106689453,-21.17803192138672,-21.17803382873535,-21.178037643432617,-21.17803955078125,-21.178043365478516,-21.17804718017578,-21.178049087524414,-21.17805290222168,-21.178054809570312,-21.178058624267578,-21.178062438964844,-21.178064346313477,-21.178070068359375,-21.178070068359375,-21.17807388305664,-21.178077697753906,-21.17807960510254,-21.178083419799805,-21.178085327148438,-21.17808723449707,-21.178091049194336,-21.1780948638916,-21.178096771240234,-21.1781005859375,-21.178102493286133,-21.178102493286133,-21.1781063079834,-21.178110122680664,-21.178112030029297,-21.17811393737793,-21.178115844726562,-21.178117752075195,-21.178119659423828,-21.17812156677246,-21.178123474121094,-21.178123474121094,-21.178125381469727,-21.178125381469727,-21.17812728881836,-21.17812728881836,-21.178129196166992,-21.178129196166992,-21.178131103515625,-21.178131103515625,-21.178131103515625,-21.178131103515625,-21.178131103515625,-21.178129196166992,-21.178129196166992,-21.17812728881836,-21.17812728881836,-21.178125381469727,-21.178125381469727,-21.17812156677246,-21.178119659423828,-21.178117752075195,-21.178115844726562,-21.178112030029297,-21.178112030029297,-21.178110122680664,-21.1781063079834,-21.178104400634766,-21.178102493286133,-21.178098678588867,-21.178096771240234,-21.1780948638916,-21.178091049194336,-21.17808723449707,-21.178085327148438,-21.178085327148438,-21.178081512451172,-21.178077697753906,-21.178075790405273,-21.178071975708008,-21.178070068359375,-21.178068161010742,-21.17806625366211,-21.178062438964844,-21.178062438964844,-21.178062438964844,-21.178058624267578,-21.178056716918945,-21.178054809570312,-21.178054809570312,-21.178050994873047,-21.17804718017578,-21.17804718017578,-21.17804527282715,-21.17804527282715,-21.17804527282715,-21.178041458129883,-21.178041458129883,-21.17803955078125,-21.178035736083984,-21.17803382873535,-21.17803192138672,-21.17803192138672,-21.178030014038086,-21.178028106689453],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"#EF553B","size":3},"mode":"markers","name":"cluster 1","x":[11.032422065734863,11.032379150390625,11.032336235046387,11.032295227050781,11.03225326538086,11.032210350036621,11.0321683883667,11.032127380371094,11.032085418701172,11.0320463180542,11.032003402709961,11.031963348388672,11.0319242477417,11.031888961791992,11.031850814819336,11.031819343566895,11.03178596496582,11.031750679016113,11.031717300415039,11.031685829162598,11.03165340423584,11.031622886657715,11.031594276428223,11.031569480895996,11.031542778015137,11.031518936157227,11.031494140625,11.03147029876709,11.031445503234863,11.031424522399902,11.031401634216309,11.031381607055664,11.031359672546387,11.031340599060059,11.031323432922363,11.031304359436035,11.031285285949707,11.031268119812012,11.03125,11.031231880187988,11.031213760375977,11.031197547912598,11.031179428100586,11.031158447265625,11.03114128112793,11.031120300292969,11.03110408782959,11.031084060668945,11.031065940856934,11.031044960021973,11.031031608581543,11.031023025512695,11.031010627746582,11.03099536895752,11.030983924865723,11.030973434448242,11.030961990356445,11.030950546264648,11.030940055847168,11.030929565429688,11.030919075012207,11.030911445617676,11.030902862548828,11.030896186828613,11.030888557434082,11.03088092803955,11.03087329864502,11.030865669250488,11.030858039855957,11.030848503112793,11.030840873718262,11.030834197998047,11.030828475952148,11.030821800231934,11.030816078186035,11.03080940246582,11.030804634094238,11.030799865722656,11.030793190002441,11.030786514282227,11.030784606933594,11.030784606933594,11.030784606933594,11.030782699584961,11.030781745910645,11.030781745910645,11.030781745910645,11.030780792236328,11.030780792236328,11.030780792236328,11.030780792236328,11.030777931213379,11.030778884887695,11.030778884887695,11.030777931213379,11.030777931213379,11.030780792236328,11.030781745910645,11.030783653259277,11.030786514282227,11.030787467956543,11.030789375305176,11.030791282653809,11.030792236328125,11.030793190002441,11.03079605102539,11.030797958374023,11.030799865722656,11.030800819396973,11.030803680419922,11.030806541442871,11.030806541442871,11.030808448791504,11.030810356140137,11.03081226348877,11.030814170837402,11.030815124511719,11.030817031860352,11.030818939208984,11.030818939208984,11.0308198928833,11.03082275390625,11.03082275390625,11.03082275390625,11.03082275390625,11.03082275390625,11.030823707580566,11.030824661254883,11.0308256149292,11.0308256149292,11.030826568603516,11.030827522277832,11.030828475952148,11.030830383300781,11.030832290649414,11.030834197998047,11.030835151672363,11.030837059020996,11.030839920043945,11.030842781066895,11.03084659576416,11.030850410461426,11.030854225158691,11.03085708618164,11.03085994720459,11.030864715576172,11.030868530273438,11.030871391296387,11.030876159667969,11.030879020690918,11.030882835388184,11.03088665008545,11.030890464782715,11.03089714050293,11.030900001525879,11.030908584594727,11.030913352966309,11.030919075012207,11.030922889709473,11.030930519104004,11.03093433380127,11.030941009521484,11.030945777893066,11.030951499938965,11.030957221984863,11.030963897705078,11.030969619750977,11.030976295471191,11.03098201751709,11.030988693237305,11.030994415283203,11.031001091003418,11.03100872039795,11.031015396118164,11.031022071838379,11.031028747558594,11.031036376953125,11.03104305267334,11.031050682067871,11.031057357788086,11.031064987182617,11.031072616577148,11.031079292297363,11.031086921691895,11.03109359741211,11.031102180480957,11.031109809875488,11.031118392944336,11.031126022338867,11.031133651733398,11.03114128112793,11.031148910522461,11.031158447265625,11.031166076660156,11.031174659729004,11.031181335449219,11.031190872192383,11.031197547912598,11.031208038330078,11.031216621398926,11.031225204467773,11.031234741210938,11.031243324279785,11.031250953674316,11.03126335144043,11.03127384185791,11.03128433227539,11.031293869018555,11.031325340270996,11.031320571899414,11.031316757202148,11.031312942504883,11.031309127807617,11.031305313110352,11.03130054473877,11.031296730041504,11.031292915344238,11.031289100646973,11.031285285949707,11.031280517578125,11.031275749206543,11.031270980834961,11.031266212463379,11.031262397766113,11.031255722045898,11.031250953674316,11.031244277954102,11.03123950958252,11.031233787536621,11.031227111816406,11.031222343444824,11.03121566772461,11.031209945678711,11.031204223632812,11.031197547912598,11.0311918258667,11.031185150146484,11.031179428100586,11.031172752380371,11.031167984008789,11.031161308288574,11.031156539916992,11.03115177154541,11.031145095825195,11.03114128112793,11.031134605407715,11.031129837036133,11.03112506866455,11.031119346618652,11.031113624572754],"y":[10.844332695007324,10.844335556030273,10.844337463378906,10.844339370727539,10.844343185424805,10.84434700012207,10.844351768493652,10.84435749053955,10.844361305236816,10.844364166259766,10.844364166259766,10.844369888305664,10.844375610351562,10.844383239746094,10.844388961791992,10.84439468383789,10.844401359558105,10.844407081604004,10.844413757324219,10.844417572021484,10.844425201416016,10.844433784484863,10.844437599182129,10.84444522857666,10.84444808959961,10.844454765319824,10.844461441040039,10.844467163085938,10.844472885131836,10.844482421875,10.844484329223633,10.844489097595215,10.84449291229248,10.844494819641113,10.844497680664062,10.844499588012695,10.844501495361328,10.844503402709961,10.84450626373291,10.844510078430176,10.844514846801758,10.844518661499023,10.844521522521973,10.844526290893555,10.84453296661377,10.844537734985352,10.844541549682617,10.8445463180542,10.844551086425781,10.844557762145996,10.844563484191895,10.84457015991211,10.84457778930664,10.844584465026855,10.844590187072754,10.844597816467285,10.844603538513184,10.844610214233398,10.84461784362793,10.844625473022461,10.844632148742676,10.844637870788574,10.844642639160156,10.844648361206055,10.844654083251953,10.844659805297852,10.84466552734375,10.844671249389648,10.844676971435547,10.844683647155762,10.844691276550293,10.844696044921875,10.844703674316406,10.844709396362305,10.84471607208252,10.844722747802734,10.84472942352295,10.844735145568848,10.84473991394043,10.844745635986328,10.844749450683594,10.844754219055176,10.844758987426758,10.844762802124023,10.844767570495605,10.844772338867188,10.84477710723877,10.844781875610352,10.84478759765625,10.844792366027832,10.844799041748047,10.844802856445312,10.844807624816895,10.844813346862793,10.844818115234375,10.844822883605957,10.844828605651855,10.84483528137207,10.844840049743652,10.844846725463867,10.844853401184082,10.84485912322998,10.844864845275879,10.844869613647461,10.844873428344727,10.844880104064941,10.844883918762207,10.844890594482422,10.844894409179688,10.844900131225586,10.844902992248535,10.8449068069458,10.844910621643066,10.844915390014648,10.844918251037598,10.84492301940918,10.844928741455078,10.844935417175293,10.844939231872559,10.84494400024414,10.844948768615723,10.844954490661621,10.84495735168457,10.844962120056152,10.844966888427734,10.844971656799316,10.844976425170898,10.844980239868164,10.84498405456543,10.844987869262695,10.844991683959961,10.844995498657227,10.844999313354492,10.845002174377441,10.84500503540039,10.845006942749023,10.845008850097656,10.845010757446289,10.845011711120605,10.845012664794922,10.845014572143555,10.845014572143555,10.845015525817871,10.845015525817871,10.845014572143555,10.845014572143555,10.845014572143555,10.845012664794922,10.845012664794922,10.845011711120605,10.845008850097656,10.84500789642334,10.845005989074707,10.84500503540039,10.845001220703125,10.845001220703125,10.844999313354492,10.844996452331543,10.844993591308594,10.844991683959961,10.844987869262695,10.844985008239746,10.844982147216797,10.844979286193848,10.844976425170898,10.844972610473633,10.844968795776367,10.844964981079102,10.84496021270752,10.844956398010254,10.844950675964355,10.84494686126709,10.844943046569824,10.844937324523926,10.844931602478027,10.844925880432129,10.84492015838623,10.844914436340332,10.84490966796875,10.844903945922852,10.844898223876953,10.844891548156738,10.84488582611084,10.844880104064941,10.844871520996094,10.844866752624512,10.844858169555664,10.84485149383545,10.844843864440918,10.844836235046387,10.844828605651855,10.844820022583008,10.844812393188477,10.844803810119629,10.844794273376465,10.844785690307617,10.844775199890137,10.844764709472656,10.844756126403809,10.844745635986328,10.844735145568848,10.84472370147705,10.84471321105957,10.84469985961914,10.844690322875977,10.844677925109863,10.844664573669434,10.844651222229004,10.844606399536133,10.844611167907715,10.844616889953613,10.844621658325195,10.844627380371094,10.844632148742676,10.844636917114258,10.84464168548584,10.844648361206055,10.84465217590332,10.844655990600586,10.844659805297852,10.844664573669434,10.844667434692383,10.844672203063965,10.844676971435547,10.844679832458496,10.844682693481445,10.844686508178711,10.844690322875977,10.844694137573242,10.844697952270508,10.844700813293457,10.844703674316406,10.844705581665039,10.844709396362305,10.844712257385254,10.844714164733887,10.844717979431152,10.844719886779785,10.844719886779785,10.844721794128418,10.84472370147705,10.8447265625,10.844727516174316,10.844730377197266,10.844731330871582,10.844733238220215,10.844735145568848,10.84473705291748,10.844738006591797,10.84473991394043],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"#00CC96","size":3},"mode":"markers","name":"cluster 2","x":[-18.723033905029297,-18.7230281829834,-18.723024368286133,-18.723026275634766,-18.723024368286133,-18.723024368286133,-18.723020553588867,-18.7230167388916,-18.7230167388916,-18.723007202148438,-18.722999572753906,-18.72299575805664,-18.72298812866211,-18.722980499267578,-18.722972869873047,-18.722965240478516,-18.72295570373535,-18.722946166992188,-18.722936630249023,-18.72292709350586,-18.722909927368164,-18.722896575927734,-18.722883224487305,-18.722871780395508,-18.72286033630371,-18.722848892211914,-18.722837448120117,-18.722824096679688,-18.72281265258789,-18.72279930114746,-18.72278594970703,-18.722774505615234,-18.722763061523438,-18.72275161743164,-18.722736358642578,-18.722726821899414,-18.72271728515625,-18.72270393371582,-18.722692489624023,-18.722681045532227,-18.722667694091797,-18.722654342651367,-18.722640991210938,-18.722631454467773,-18.722612380981445,-18.72260284423828,-18.72258758544922,-18.722572326660156,-18.722558975219727,-18.722543716430664,-18.722532272338867,-18.722518920898438,-18.722503662109375,-18.722490310668945,-18.72247886657715,-18.72246551513672,-18.722454071044922,-18.722442626953125,-18.72243309020996,-18.722423553466797,-18.722414016723633,-18.722400665283203,-18.72239875793457,-18.722393035888672,-18.722389221191406,-18.72238540649414,-18.722379684448242,-18.72237777709961,-18.72237205505371,-18.722366333007812,-18.722362518310547,-18.72235679626465,-18.722352981567383,-18.722347259521484,-18.72234344482422,-18.722339630126953,-18.72233772277832,-18.722333908081055,-18.722333908081055,-18.722333908081055,-18.722333908081055,-18.722332000732422,-18.722332000732422,-18.722332000732422,-18.722332000732422,-18.72233009338379,-18.722332000732422,-18.722333908081055,-18.722333908081055,-18.722333908081055,-18.722333908081055,-18.722333908081055,-18.722333908081055,-18.722333908081055,-18.722332000732422,-18.722333908081055,-18.72233772277832,-18.72233772277832,-18.722339630126953,-18.722341537475586,-18.722341537475586,-18.72234344482422,-18.72234535217285,-18.722347259521484,-18.722347259521484,-18.722349166870117,-18.72235107421875,-18.722352981567383,-18.722352981567383,-18.722352981567383,-18.722352981567383,-18.722352981567383,-18.722352981567383,-18.722354888916016,-18.722354888916016,-18.722354888916016,-18.722354888916016,-18.72235679626465,-18.72235870361328,-18.72235870361328,-18.72235870361328,-18.722362518310547,-18.722362518310547,-18.72236442565918,-18.72236442565918,-18.722368240356445,-18.722368240356445,-18.722370147705078,-18.722370147705078,-18.722373962402344,-18.72237777709961,-18.72237777709961,-18.722379684448242,-18.722381591796875,-18.72238540649414,-18.722387313842773,-18.722389221191406,-18.72239112854004,-18.722393035888672,-18.72239875793457,-18.722400665283203,-18.722400665283203,-18.722402572631836,-18.7224063873291,-18.7224063873291,-18.722408294677734,-18.722412109375,-18.722415924072266,-18.7224178314209,-18.72241973876953,-18.722423553466797,-18.72242546081543,-18.72242546081543,-18.722429275512695,-18.72243309020996,-18.722434997558594,-18.722436904907227,-18.722440719604492,-18.722442626953125,-18.72244644165039,-18.722448348999023,-18.72245216369629,-18.722455978393555,-18.722457885742188,-18.722463607788086,-18.72246551513672,-18.722469329833984,-18.722475051879883,-18.72247886657715,-18.72248077392578,-18.72248649597168,-18.722490310668945,-18.72249412536621,-18.722497940063477,-18.722503662109375,-18.72250747680664,-18.722511291503906,-18.722515106201172,-18.722517013549805,-18.722522735595703,-18.722524642944336,-18.7225284576416,-18.722532272338867,-18.722536087036133,-18.7225399017334,-18.72254180908203,-18.722545623779297,-18.72254753112793,-18.722551345825195,-18.72255516052246,-18.722557067871094,-18.722558975219727,-18.72256088256836,-18.722562789916992,-18.722566604614258,-18.72256851196289,-18.722570419311523,-18.722570419311523,-18.722572326660156,-18.72257423400879,-18.722576141357422,-18.722578048706055,-18.722578048706055,-18.722578048706055,-18.722579956054688,-18.72258186340332,-18.72258186340332,-18.722583770751953,-18.722583770751953,-18.722583770751953,-18.722583770751953,-18.72258186340332,-18.72258186340332,-18.72258186340332,-18.72258186340332,-18.72258186340332,-18.722579956054688,-18.722579956054688,-18.722579956054688,-18.722579956054688,-18.722578048706055,-18.722578048706055,-18.722578048706055,-18.722578048706055,-18.722578048706055,-18.722578048706055,-18.72257423400879,-18.72257423400879,-18.722572326660156,-18.722570419311523,-18.722570419311523,-18.72256851196289,-18.722566604614258,-18.722564697265625,-18.722562789916992,-18.722562789916992,-18.722558975219727,-18.72255516052246,-18.72255516052246,-18.722553253173828,-18.722551345825195,-18.72254753112793,-18.72254753112793,-18.722545623779297,-18.722543716430664,-18.72254180908203,-18.7225399017334,-18.722537994384766,-18.7225341796875,-18.722532272338867],"y":[-5.475583076477051,-5.475590705871582,-5.475595951080322,-5.475601673126221,-5.475605487823486,-5.475610256195068,-5.475616931915283,-5.475622653961182,-5.475627899169922,-5.475632667541504,-5.475641250610352,-5.475649356842041,-5.475656509399414,-5.475666522979736,-5.475677490234375,-5.4756879806518555,-5.475698947906494,-5.4757080078125,-5.475718975067139,-5.475729465484619,-5.475739479064941,-5.4757513999938965,-5.475761890411377,-5.475774765014648,-5.4757866859436035,-5.475797176361084,-5.4758076667785645,-5.475818157196045,-5.475829601287842,-5.475842475891113,-5.475852966308594,-5.475863456726074,-5.475873947143555,-5.475883960723877,-5.475894451141357,-5.475902557373047,-5.475912094116211,-5.475921630859375,-5.475930690765381,-5.475939750671387,-5.475950717926025,-5.4759602546691895,-5.475967884063721,-5.475977897644043,-5.475985527038574,-5.4759955406188965,-5.476005554199219,-5.476012706756592,-5.476019859313965,-5.47602653503418,-5.476033687591553,-5.476040840148926,-5.476047039031982,-5.476053714752197,-5.476059436798096,-5.476064682006836,-5.476070404052734,-5.47607421875,-5.476077079772949,-5.476080894470215,-5.476085186004639,-5.476086616516113,-5.476088523864746,-5.4760894775390625,-5.476090431213379,-5.476090908050537,-5.4760918617248535,-5.476092338562012,-5.476092338562012,-5.476093292236328,-5.476093292236328,-5.476093769073486,-5.476093292236328,-5.476093292236328,-5.4760918617248535,-5.476090908050537,-5.476090431213379,-5.4760894775390625,-5.47608757019043,-5.476086616516113,-5.476085186004639,-5.476084232330322,-5.476085186004639,-5.476086616516113,-5.4760870933532715,-5.4760870933532715,-5.476086616516113,-5.476085662841797,-5.4760847091674805,-5.476083278656006,-5.4760823249816895,-5.476080894470215,-5.476079940795898,-5.47607946395874,-5.476078987121582,-5.476078033447266,-5.476078033447266,-5.476077556610107,-5.476078033447266,-5.476077556610107,-5.476078033447266,-5.476078033447266,-5.476078033447266,-5.476078033447266,-5.476077556610107,-5.476076602935791,-5.476076126098633,-5.476075649261475,-5.476075172424316,-5.476074695587158,-5.476073741912842,-5.476072788238525,-5.476072311401367,-5.476072788238525,-5.476071834564209,-5.476070880889893,-5.476070404052734,-5.476069450378418,-5.476068019866943,-5.476066589355469,-5.476065158843994,-5.476063251495361,-5.4760613441467285,-5.4760589599609375,-5.476056098937988,-5.476053714752197,-5.476050853729248,-5.476048469543457,-5.476045608520508,-5.476043224334717,-5.476039886474609,-5.476036548614502,-5.476033687591553,-5.476030349731445,-5.476027488708496,-5.476024150848389,-5.476020336151123,-5.476017475128174,-5.476013660430908,-5.476010322570801,-5.476006507873535,-5.476003170013428,-5.475998878479004,-5.4759955406188965,-5.475991249084473,-5.475987434387207,-5.475983619689941,-5.475979328155518,-5.475975513458252,-5.475971698760986,-5.475967884063721,-5.475964069366455,-5.4759602546691895,-5.475956439971924,-5.475952625274658,-5.475948333740234,-5.4759440422058105,-5.475939750671387,-5.475934982299805,-5.475931167602539,-5.475926399230957,-5.475921630859375,-5.475917339324951,-5.475912570953369,-5.475907802581787,-5.475903511047363,-5.475898742675781,-5.475893497467041,-5.475888729095459,-5.475884437561035,-5.4758806228637695,-5.4758758544921875,-5.475872039794922,-5.475868225097656,-5.475865364074707,-5.475861549377441,-5.475858688354492,-5.475855827331543,-5.475852966308594,-5.4758501052856445,-5.4758477210998535,-5.4758453369140625,-5.4758429527282715,-5.4758405685424805,-5.475838661193848,-5.475836753845215,-5.47583532333374,-5.475833892822266,-5.475832462310791,-5.475831985473633,-5.475831031799316,-5.475830078125,-5.475829601287842,-5.475830078125,-5.475830078125,-5.475830554962158,-5.475831985473633,-5.475832462310791,-5.475833892822266,-5.475834846496582,-5.475836277008057,-5.475837707519531,-5.475839614868164,-5.475841522216797,-5.47584342956543,-5.4758453369140625,-5.475847244262695,-5.475849151611328,-5.475851058959961,-5.475852966308594,-5.475856304168701,-5.475858688354492,-5.475861072540283,-5.475863456726074,-5.475866317749023,-5.4758687019348145,-5.475871562957764,-5.475873947143555,-5.475876808166504,-5.475879192352295,-5.475881576538086,-5.475884437561035,-5.475886821746826,-5.475889205932617,-5.475891590118408,-5.475893974304199,-5.475895404815674,-5.475897789001465,-5.475899696350098,-5.475902080535889,-5.47590446472168,-5.4759063720703125,-5.475908279418945,-5.475910663604736,-5.475912094116211,-5.475914478302002,-5.475915908813477,-5.475917339324951,-5.475918769836426,-5.475920677185059,-5.475922107696533,-5.475923538208008,-5.475924968719482,-5.475926399230957,-5.47592830657959,-5.4759297370910645,-5.475931167602539,-5.475932598114014,-5.4759345054626465,-5.475935935974121],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"#AB63FA","size":3},"mode":"markers","name":"cluster 3","x":[-20.593740463256836,-20.593738555908203,-20.593730926513672,-20.59372329711914,-20.59371566772461,-20.593711853027344,-20.593700408935547,-20.59369659423828,-20.593685150146484,-20.593679428100586,-20.593671798706055,-20.593664169311523,-20.593660354614258,-20.593650817871094,-20.593643188476562,-20.593639373779297,-20.593629837036133,-20.5936279296875,-20.59362030029297,-20.59361457824707,-20.593608856201172,-20.59360122680664,-20.59359359741211,-20.59358787536621,-20.593584060668945,-20.593578338623047,-20.593576431274414,-20.59357452392578,-20.593570709228516,-20.593564987182617,-20.59356689453125,-20.593564987182617,-20.59356117248535,-20.593563079833984,-20.59356117248535,-20.59356117248535,-20.59356117248535,-20.59355926513672,-20.593564987182617,-20.593564987182617,-20.593564987182617,-20.59356689453125,-20.593568801879883,-20.59357261657715,-20.59357452392578,-20.593578338623047,-20.593584060668945,-20.593584060668945,-20.59358787536621,-20.593591690063477,-20.59359359741211,-20.593599319458008,-20.59360122680664,-20.593605041503906,-20.593610763549805,-20.59361457824707,-20.59362030029297,-20.5936279296875,-20.593631744384766,-20.593637466430664,-20.593647003173828,-20.593650817871094,-20.593658447265625,-20.59366798400879,-20.59367561340332,-20.59368324279785,-20.593692779541016,-20.593700408935547,-20.593708038330078,-20.59371566772461,-20.59372901916504,-20.59373664855957,-20.593746185302734,-20.5937557220459,-20.59376335144043,-20.59377098083496,-20.593780517578125,-20.59379005432129,-20.593799591064453,-20.593809127807617,-20.59381675720215,-20.59382438659668,-20.59383201599121,-20.593841552734375,-20.59385108947754,-20.593856811523438,-20.59386444091797,-20.593875885009766,-20.59388542175293,-20.593891143798828,-20.593900680541992,-20.593910217285156,-20.593917846679688,-20.59392738342285,-20.593936920166016,-20.59394645690918,-20.593955993652344,-20.593963623046875,-20.593971252441406,-20.59398078918457,-20.5939884185791,-20.593997955322266,-20.59400749206543,-20.59401512145996,-20.594022750854492,-20.594030380249023,-20.59403419494629,-20.594043731689453,-20.59404945373535,-20.594053268432617,-20.59406089782715,-20.594066619873047,-20.594072341918945,-20.594079971313477,-20.594083786010742,-20.594091415405273,-20.59409523010254,-20.594099044799805,-20.594104766845703,-20.59410858154297,-20.594112396240234,-20.5941162109375,-20.5941219329834,-20.59412384033203,-20.59412956237793,-20.594133377075195,-20.594135284423828,-20.594139099121094,-20.594141006469727,-20.59414291381836,-20.594144821166992,-20.594146728515625,-20.594148635864258,-20.59415054321289,-20.594152450561523,-20.594154357910156,-20.594154357910156,-20.59415626525879,-20.59415626525879,-20.594158172607422,-20.594158172607422,-20.594158172607422,-20.594158172607422,-20.594158172607422,-20.59415626525879,-20.59415626525879,-20.594154357910156,-20.594154357910156,-20.59415054321289,-20.594148635864258,-20.594146728515625,-20.594144821166992,-20.594141006469727,-20.594139099121094,-20.594135284423828,-20.594133377075195,-20.59412956237793,-20.594125747680664,-20.59412384033203,-20.594118118286133,-20.5941162109375,-20.5941104888916,-20.594106674194336,-20.59410285949707,-20.594100952148438,-20.594097137451172,-20.594093322753906,-20.594087600708008,-20.594083786010742,-20.594078063964844,-20.594074249267578,-20.594070434570312,-20.594064712524414,-20.59406089782715,-20.59405517578125,-20.594051361083984,-20.59404754638672,-20.59404182434082,-20.594036102294922,-20.594030380249023,-20.594026565551758,-20.594024658203125,-20.594018936157227,-20.59401512145996,-20.594009399414062,-20.594005584716797,-20.59400177001953,-20.5939998626709,-20.593994140625,-20.593990325927734,-20.593984603881836,-20.59398078918457,-20.593976974487305,-20.593971252441406,-20.593969345092773,-20.593965530395508,-20.593961715698242,-20.593955993652344,-20.59395408630371,-20.593950271606445,-20.59394645690918,-20.593944549560547,-20.59393882751465,-20.593936920166016,-20.593931198120117,-20.593929290771484,-20.59392547607422,-20.593923568725586,-20.593921661376953,-20.593917846679688,-20.593915939331055,-20.593914031982422,-20.593910217285156,-20.593910217285156,-20.593908309936523,-20.593904495239258,-20.593900680541992,-20.593900680541992,-20.593900680541992,-20.593896865844727,-20.593896865844727,-20.593894958496094,-20.593894958496094,-20.59389305114746,-20.59389305114746,-20.59389305114746,-20.593891143798828,-20.593891143798828,-20.593889236450195,-20.593889236450195,-20.593889236450195,-20.593889236450195,-20.593889236450195,-20.593889236450195,-20.593889236450195,-20.593889236450195,-20.593889236450195,-20.593889236450195,-20.593889236450195,-20.593889236450195,-20.593889236450195,-20.593889236450195,-20.593889236450195,-20.593889236450195,-20.593889236450195,-20.593889236450195,-20.593889236450195,-20.593889236450195,-20.593891143798828,-20.593891143798828],"y":[9.10008430480957,9.100083351135254,9.100076675415039,9.100069999694824,9.100062370300293,9.100055694580078,9.100048065185547,9.100040435791016,9.100031852722168,9.100024223327637,9.100016593933105,9.100008964538574,9.10000228881836,9.099995613098145,9.09998607635498,9.099976539611816,9.099966049194336,9.099955558776855,9.09994125366211,9.099928855895996,9.099913597106934,9.099899291992188,9.099884033203125,9.099867820739746,9.099853515625,9.099837303161621,9.099822044372559,9.09980583190918,9.099790573120117,9.099773406982422,9.099760055541992,9.099743843078613,9.099724769592285,9.099709510803223,9.099693298339844,9.099676132202148,9.099662780761719,9.099647521972656,9.09963607788086,9.099623680114746,9.099610328674316,9.099596977233887,9.099583625793457,9.099570274353027,9.09955883026123,9.0995454788208,9.09953498840332,9.09952449798584,9.09951400756836,9.099503517150879,9.099493026733398,9.099483489990234,9.099475860595703,9.099467277526855,9.09946060180664,9.099454879760742,9.099448204040527,9.099443435668945,9.09943962097168,9.099434852600098,9.099430084228516,9.099424362182617,9.099418640136719,9.099414825439453,9.099411010742188,9.099407196044922,9.099404335021973,9.09940242767334,9.09939956665039,9.099397659301758,9.099396705627441,9.099393844604492,9.099390029907227,9.09938907623291,9.099386215209961,9.099383354187012,9.099382400512695,9.099380493164062,9.099379539489746,9.099379539489746,9.099379539489746,9.099380493164062,9.099381446838379,9.099383354187012,9.099386215209961,9.099387168884277,9.099390029907227,9.09939193725586,9.099393844604492,9.099397659301758,9.09939956665039,9.099401473999023,9.099404335021973,9.099407196044922,9.099410057067871,9.09941291809082,9.09941577911377,9.099419593811035,9.099422454833984,9.099425315856934,9.099430084228516,9.099432945251465,9.09943675994873,9.09943962097168,9.099443435668945,9.099446296691895,9.099448204040527,9.09945297241211,9.099455833435059,9.099458694458008,9.099462509155273,9.099466323852539,9.099469184875488,9.099472045898438,9.09947395324707,9.099477767944336,9.099479675292969,9.099481582641602,9.099485397338867,9.099488258361816,9.099492073059082,9.099495887756348,9.099499702453613,9.099502563476562,9.099506378173828,9.099510192871094,9.09951400756836,9.099516868591309,9.099519729614258,9.099525451660156,9.099528312683105,9.099531173706055,9.09953498840332,9.099538803100586,9.099542617797852,9.099543571472168,9.099546432495117,9.099550247192383,9.099553108215332,9.099556922912598,9.099560737609863,9.099563598632812,9.099567413330078,9.099570274353027,9.099574089050293,9.099577903747559,9.099581718444824,9.099584579467773,9.099587440490723,9.099591255187988,9.099593162536621,9.099596977233887,9.099600791931152,9.099604606628418,9.099607467651367,9.099610328674316,9.099613189697266,9.099616050720215,9.09961986541748,9.099623680114746,9.099627494812012,9.099630355834961,9.09963321685791,9.099637031555176,9.099639892578125,9.099642753601074,9.099645614624023,9.099648475646973,9.099650382995605,9.099653244018555,9.099656105041504,9.099658012390137,9.099658966064453,9.099662780761719,9.099663734436035,9.099665641784668,9.099668502807617,9.09967041015625,9.099672317504883,9.099674224853516,9.099675178527832,9.099677085876465,9.099678039550781,9.099678993225098,9.099679946899414,9.09968090057373,9.099681854248047,9.099684715270996,9.099685668945312,9.099685668945312,9.099686622619629,9.099687576293945,9.099688529968262,9.099689483642578,9.099689483642578,9.099689483642578,9.099689483642578,9.099689483642578,9.099689483642578,9.099689483642578,9.099689483642578,9.099689483642578,9.099689483642578,9.099689483642578,9.099688529968262,9.099687576293945,9.099686622619629,9.099686622619629,9.099685668945312,9.099685668945312,9.09968376159668,9.099682807922363,9.099681854248047,9.099679946899414,9.099678039550781,9.099677085876465,9.099675178527832,9.099674224853516,9.099672317504883,9.09967041015625,9.099669456481934,9.0996675491333,9.099666595458984,9.099664688110352,9.099662780761719,9.099660873413086,9.099658966064453,9.099656105041504,9.099655151367188,9.099653244018555,9.099651336669922,9.099649429321289,9.099647521972656,9.099645614624023,9.09964370727539,9.099640846252441,9.099638938903809,9.099637985229492,9.099635124206543,9.09963321685791,9.099631309509277,9.099629402160645,9.099627494812012,9.099624633789062,9.099623680114746,9.099620819091797,9.09961986541748,9.099617958068848,9.099616050720215,9.099614143371582],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"#FFA15A","size":3},"mode":"markers","name":"cluster 4","x":[-9.634173393249512,-9.634169578552246,-9.634164810180664,-9.634161949157715,-9.63415813446045,-9.63415813446045,-9.6341552734375,-9.634154319763184,-9.63415241241455,-9.634149551391602,-9.634147644042969,-9.634143829345703,-9.63414192199707,-9.634140014648438,-9.634139060974121,-9.634138107299805,-9.634137153625488,-9.634137153625488,-9.634135246276855,-9.634135246276855,-9.634138107299805,-9.634139060974121,-9.63414192199707,-9.634142875671387,-9.63414478302002,-9.634146690368652,-9.634148597717285,-9.634150505065918,-9.6341552734375,-9.634161949157715,-9.634167671203613,-9.634172439575195,-9.634175300598145,-9.634180068969727,-9.634183883666992,-9.634187698364258,-9.634190559387207,-9.634193420410156,-9.634196281433105,-9.634200096130371,-9.63420295715332,-9.634203910827637,-9.63420581817627,-9.634207725524902,-9.634207725524902,-9.634210586547852,-9.634210586547852,-9.634211540222168,-9.634211540222168,-9.634212493896484,-9.6342134475708,-9.634215354919434,-9.634217262268066,-9.6342191696167,-9.634222030639648,-9.634223937988281,-9.634227752685547,-9.634228706359863,-9.634231567382812,-9.634234428405762,-9.634238243103027,-9.634241104125977,-9.63424301147461,-9.634245872497559,-9.634249687194824,-9.634254455566406,-9.634258270263672,-9.634262084960938,-9.634264945983887,-9.634270668029785,-9.634273529052734,-9.63427734375,-9.634281158447266,-9.634284019470215,-9.63428783416748,-9.634289741516113,-9.634293556213379,-9.634295463562012,-9.634299278259277,-9.634300231933594,-9.634305953979492,-9.634312629699707,-9.634317398071289,-9.634322166442871,-9.634325981140137,-9.634329795837402,-9.634334564208984,-9.634339332580566,-9.634346961975098,-9.63435173034668,-9.634357452392578,-9.634363174438477,-9.634368896484375,-9.634374618530273,-9.634380340576172,-9.634387969970703,-9.634391784667969,-9.634397506713867,-9.634401321411133,-9.634404182434082,-9.634408950805664,-9.63441276550293,-9.634416580200195,-9.634419441223145,-9.634425163269043,-9.634428024291992,-9.634429931640625,-9.634432792663574,-9.634434700012207,-9.634437561035156,-9.634439468383789,-9.634442329406738,-9.634445190429688,-9.634448051452637,-9.63444995880127,-9.634451866149902,-9.634453773498535,-9.634455680847168,-9.634458541870117,-9.63446044921875,-9.6344633102417,-9.634466171264648,-9.634469032287598,-9.63447093963623,-9.634472846984863,-9.634476661682129,-9.634479522705078,-9.634480476379395,-9.63448429107666,-9.634486198425293,-9.634489059448242,-9.634491920471191,-9.63449478149414,-9.63449764251709,-9.634499549865723,-9.634502410888672,-9.634502410888672,-9.634505271911621,-9.634505271911621,-9.634507179260254,-9.634509086608887,-9.63451099395752,-9.634512901306152,-9.634513854980469,-9.634514808654785,-9.634514808654785,-9.634515762329102,-9.634515762329102,-9.634515762329102,-9.634515762329102,-9.634515762329102,-9.634514808654785,-9.634513854980469,-9.634512901306152,-9.63451099395752,-9.634509086608887,-9.634507179260254,-9.634505271911621,-9.634502410888672,-9.634501457214355,-9.63449764251709,-9.634496688842773,-9.634493827819824,-9.634490013122559,-9.634488105773926,-9.634485244750977,-9.634483337402344,-9.634480476379395,-9.634477615356445,-9.634474754333496,-9.634471893310547,-9.634469985961914,-9.634467124938965,-9.634464263916016,-9.634461402893066,-9.634459495544434,-9.634456634521484,-9.634453773498535,-9.634450912475586,-9.634448051452637,-9.634445190429688,-9.634442329406738,-9.634439468383789,-9.634437561035156,-9.634434700012207,-9.634431838989258,-9.634428977966309,-9.63442611694336,-9.634424209594727,-9.634420394897461,-9.634417533874512,-9.634416580200195,-9.63441276550293,-9.634410858154297,-9.634407997131348,-9.634404182434082,-9.634401321411133,-9.634398460388184,-9.63439655303955,-9.634393692016602,-9.634391784667969,-9.63438892364502,-9.634385108947754,-9.634383201599121,-9.634381294250488,-9.634378433227539,-9.63437557220459,-9.634373664855957,-9.63437271118164,-9.634370803833008,-9.634367942810059,-9.634366035461426,-9.63436508178711,-9.634363174438477,-9.63436222076416,-9.634360313415527,-9.634358406066895,-9.634357452392578,-9.634357452392578,-9.634355545043945,-9.634354591369629,-9.634353637695312,-9.63435173034668,-9.634350776672363,-9.634349822998047,-9.634349822998047,-9.634347915649414,-9.634347915649414,-9.634346961975098,-9.634346961975098,-9.634346961975098,-9.634346961975098,-9.634346961975098,-9.634345054626465,-9.634345054626465,-9.634345054626465,-9.634345054626465,-9.634345054626465,-9.634345054626465,-9.634345054626465,-9.634345054626465,-9.634346961975098,-9.634346961975098,-9.634346961975098,-9.634347915649414,-9.634347915649414,-9.634347915649414,-9.634349822998047,-9.634349822998047,-9.634350776672363],"y":[24.50714874267578,24.507144927978516,24.50714111328125,24.507137298583984,24.50713348388672,24.50713348388672,24.50712776184082,24.507125854492188,24.507123947143555,24.507118225097656,24.50712013244629,24.507118225097656,24.507118225097656,24.507118225097656,24.50711441040039,24.507116317749023,24.50711441040039,24.50711441040039,24.50711441040039,24.50711441040039,24.507112503051758,24.507112503051758,24.507112503051758,24.507112503051758,24.507112503051758,24.507110595703125,24.507110595703125,24.507112503051758,24.507118225097656,24.50711441040039,24.507116317749023,24.507112503051758,24.50711441040039,24.507118225097656,24.507118225097656,24.50712013244629,24.50712013244629,24.50712013244629,24.507122039794922,24.507125854492188,24.507123947143555,24.507123947143555,24.50712013244629,24.50712013244629,24.507118225097656,24.507116317749023,24.507112503051758,24.507110595703125,24.507108688354492,24.50710678100586,24.507104873657227,24.507102966308594,24.50710105895996,24.50710105895996,24.50710105895996,24.507097244262695,24.507099151611328,24.50709342956543,24.507089614868164,24.507089614868164,24.507089614868164,24.50708770751953,24.5070858001709,24.507083892822266,24.507081985473633,24.5070858001709,24.507083892822266,24.507081985473633,24.507080078125,24.507080078125,24.507078170776367,24.507076263427734,24.50707244873047,24.507070541381836,24.507070541381836,24.507068634033203,24.507070541381836,24.50706672668457,24.507064819335938,24.507057189941406,24.50705337524414,24.507051467895508,24.50704574584961,24.507041931152344,24.507038116455078,24.50703239440918,24.507028579711914,24.507022857666016,24.507017135620117,24.507009506225586,24.507003784179688,24.50699806213379,24.50699234008789,24.506986618041992,24.50697898864746,24.506973266601562,24.506967544555664,24.506959915161133,24.50695037841797,24.50694465637207,24.506938934326172,24.506933212280273,24.506925582885742,24.506919860839844,24.506914138793945,24.506906509399414,24.506898880004883,24.50688934326172,24.506881713867188,24.50687599182129,24.506866455078125,24.506858825683594,24.50684928894043,24.50684356689453,24.506834030151367,24.50682830810547,24.506818771362305,24.506813049316406,24.506803512573242,24.506793975830078,24.506786346435547,24.506778717041016,24.50676918029785,24.506759643554688,24.50675392150879,24.506746292114258,24.506738662719727,24.506731033325195,24.506723403930664,24.506715774536133,24.5067081451416,24.50670051574707,24.506694793701172,24.506685256958008,24.50667953491211,24.50667381286621,24.50666618347168,24.50666046142578,24.50665283203125,24.506649017333984,24.506643295288086,24.50663948059082,24.506635665893555,24.506633758544922,24.506629943847656,24.50662612915039,24.506624221801758,24.506622314453125,24.506620407104492,24.50661849975586,24.50661849975586,24.50661849975586,24.50661849975586,24.50661849975586,24.506620407104492,24.506622314453125,24.506624221801758,24.50662612915039,24.50662612915039,24.506629943847656,24.506633758544922,24.506635665893555,24.50663948059082,24.506641387939453,24.50664520263672,24.506650924682617,24.506654739379883,24.506656646728516,24.506662368774414,24.50666618347168,24.506671905517578,24.506675720214844,24.50667953491211,24.506685256958008,24.506689071655273,24.506698608398438,24.506704330444336,24.5067081451416,24.5067138671875,24.5067195892334,24.506725311279297,24.506731033325195,24.506738662719727,24.506744384765625,24.506750106811523,24.506755828857422,24.50676155090332,24.506771087646484,24.506776809692383,24.506784439086914,24.506790161132812,24.50679588317871,24.50680160522461,24.506807327270508,24.50681495666504,24.506818771362305,24.506826400756836,24.5068302154541,24.5068359375,24.5068416595459,24.50684928894043,24.506851196289062,24.506858825683594,24.506864547729492,24.50687026977539,24.506874084472656,24.506879806518555,24.506881713867188,24.506885528564453,24.50688934326172,24.50689125061035,24.506895065307617,24.50689697265625,24.506900787353516,24.50690460205078,24.50690460205078,24.506906509399414,24.50691032409668,24.50691032409668,24.506912231445312,24.506912231445312,24.506916046142578,24.506916046142578,24.506916046142578,24.50691795349121,24.506919860839844,24.506919860839844,24.506919860839844,24.506919860839844,24.506919860839844,24.506919860839844,24.506919860839844,24.506919860839844,24.506919860839844,24.506919860839844,24.506919860839844,24.506919860839844,24.506919860839844,24.506919860839844,24.50691795349121,24.506916046142578,24.506916046142578,24.506916046142578,24.506916046142578,24.506914138793945,24.506912231445312,24.506912231445312,24.506912231445312,24.506912231445312,24.50691032409668],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"#19D3F3","size":3},"mode":"markers","name":"cluster 5","x":[24.87541961669922,24.875415802001953,24.87541389465332,24.875411987304688,24.875411987304688,24.875411987304688,24.875411987304688,24.875411987304688,24.875408172607422,24.875396728515625,24.875394821166992,24.875391006469727,24.875385284423828,24.875385284423828,24.87537956237793,24.87537384033203,24.875368118286133,24.8753604888916,24.87535285949707,24.875343322753906,24.875335693359375,24.87532615661621,24.875316619873047,24.875307083129883,24.87529945373535,24.875289916992188,24.875288009643555,24.875280380249023,24.87527847290039,24.875272750854492,24.87526512145996,24.875259399414062,24.87525177001953,24.8752384185791,24.875232696533203,24.87522315979004,24.87521743774414,24.875213623046875,24.875205993652344,24.875198364257812,24.875192642211914,24.875186920166016,24.875179290771484,24.87516975402832,24.875165939331055,24.875154495239258,24.875150680541992,24.87514877319336,24.875146865844727,24.875144958496094,24.875139236450195,24.875137329101562,24.875137329101562,24.87512969970703,24.8751277923584,24.875123977661133,24.8751220703125,24.875112533569336,24.875112533569336,24.87510871887207,24.875106811523438,24.875097274780273,24.875091552734375,24.87508773803711,24.875078201293945,24.875072479248047,24.875072479248047,24.875062942504883,24.875059127807617,24.875051498413086,24.875045776367188,24.875043869018555,24.875036239624023,24.875030517578125,24.875024795532227,24.875017166137695,24.875015258789062,24.875009536743164,24.87500762939453,24.875003814697266,24.874998092651367,24.874996185302734,24.874990463256836,24.874988555908203,24.87498664855957,24.874984741210938,24.874982833862305,24.874977111816406,24.874975204467773,24.874971389770508,24.874967575073242,24.87496566772461,24.874961853027344,24.87495994567871,24.874954223632812,24.874950408935547,24.87494468688965,24.874940872192383,24.87493324279785,24.874927520751953,24.874921798706055,24.874916076660156,24.874910354614258,24.874902725219727,24.87489891052246,24.874893188476562,24.874887466430664,24.8748836517334,24.874876022338867,24.8748722076416,24.874866485595703,24.874862670898438,24.874862670898438,24.874855041503906,24.874853134155273,24.87485122680664,24.874847412109375,24.874845504760742,24.87484359741211,24.87484359741211,24.874839782714844,24.874835968017578,24.874834060668945,24.87483024597168,24.874828338623047,24.87482452392578,24.87482261657715,24.87482261657715,24.874820709228516,24.874818801879883,24.874818801879883,24.87481689453125,24.87481689453125,24.874818801879883,24.874818801879883,24.874818801879883,24.87481689453125,24.874818801879883,24.874818801879883,24.87482261657715,24.87482261657715,24.87482452392578,24.874826431274414,24.874828338623047,24.874832153320312,24.874834060668945,24.87483787536621,24.874841690063477,24.874845504760742,24.874853134155273,24.87485694885254,24.874866485595703,24.87487030029297,24.874876022338867,24.874881744384766,24.874887466430664,24.874893188476562,24.874897003173828,24.874902725219727,24.874908447265625,24.874914169311523,24.874919891357422,24.874923706054688,24.87493133544922,24.874935150146484,24.874940872192383,24.874940872192383,24.87494468688965,24.874950408935547,24.874954223632812,24.87495994567871,24.87496566772461,24.874971389770508,24.874977111816406,24.874980926513672,24.874982833862305,24.874988555908203,24.87499237060547,24.874998092651367,24.875,24.875003814697266,24.875009536743164,24.87501335144043,24.875017166137695,24.87502098083496,24.875024795532227,24.875028610229492,24.875030517578125,24.875038146972656,24.875038146972656,24.875041961669922,24.875045776367188,24.87504768371582,24.875049591064453,24.875051498413086,24.87505340576172,24.87505531311035,24.875059127807617,24.87506103515625,24.87506103515625,24.87506103515625,24.875064849853516,24.875064849853516,24.875064849853516,24.875064849853516,24.875064849853516,24.875064849853516,24.875064849853516,24.875064849853516,24.875064849853516,24.875064849853516,24.875064849853516,24.875064849853516,24.875064849853516,24.875064849853516,24.875064849853516,24.875062942504883,24.875062942504883,24.87506103515625,24.87506103515625,24.87506103515625,24.87506103515625,24.87506103515625,24.87506103515625,24.87506103515625,24.875059127807617,24.875059127807617,24.875059127807617,24.875059127807617,24.875059127807617,24.875059127807617,24.875059127807617,24.875057220458984,24.875057220458984,24.87505531311035,24.87505531311035,24.87505531311035,24.87505531311035,24.87505340576172,24.87505340576172,24.87505340576172,24.87505340576172,24.87505340576172,24.875049591064453,24.875049591064453,24.875045776367188,24.875045776367188,24.875045776367188,24.875045776367188,24.875043869018555],"y":[3.724310874938965,3.7243382930755615,3.7243645191192627,3.7243940830230713,3.72442364692688,3.7244532108306885,3.7244808673858643,3.724508047103882,3.7245354652404785,3.724562406539917,3.7245891094207764,3.7246148586273193,3.7246413230895996,3.724667549133301,3.7246932983398438,3.724717855453491,3.724745750427246,3.724774122238159,3.724801778793335,3.7248282432556152,3.7248544692993164,3.7248802185058594,3.7249059677124023,3.724929094314575,3.724951982498169,3.724975109100342,3.724996566772461,3.7250142097473145,3.7250325679779053,3.725050449371338,3.725069999694824,3.725088357925415,3.7251064777374268,3.725123405456543,3.725140333175659,3.7251546382904053,3.725172281265259,3.7251884937286377,3.725203037261963,3.7252182960510254,3.725234270095825,3.7252495288848877,3.7252633571624756,3.725276470184326,3.7252891063690186,3.7253010272979736,3.725314140319824,3.7253267765045166,3.7253382205963135,3.725349187850952,3.7253599166870117,3.7253713607788086,3.725381851196289,3.725391387939453,3.7254014015197754,3.7254111766815186,3.725421190261841,3.7254300117492676,3.72544002532959,3.7254483699798584,3.7254574298858643,3.7254655361175537,3.7254750728607178,3.725484609603882,3.7254951000213623,3.725505828857422,3.725515604019165,3.7255241870880127,3.7255330085754395,3.725539445877075,3.725545644760132,3.725550651550293,3.7255544662475586,3.7255585193634033,3.725562572479248,3.725564479827881,3.7255666255950928,3.7255678176879883,3.7255685329437256,3.725569486618042,3.725569009780884,3.7255682945251465,3.7255682945251465,3.7255678176879883,3.725567102432251,3.7255666255950928,3.7255656719207764,3.7255637645721436,3.72556209564209,3.725560188293457,3.725558280944824,3.7255568504333496,3.725555896759033,3.7255539894104004,3.7255520820617676,3.725550651550293,3.7255492210388184,3.7255475521087646,3.725545644760132,3.725543260574341,3.725541353225708,3.725539207458496,3.725536584854126,3.725534200668335,3.725531816482544,3.7255287170410156,3.7255258560180664,3.7255234718322754,3.725520372390747,3.7255170345306396,3.7255139350891113,3.725510835647583,3.7255074977874756,3.7255032062530518,3.7254998683929443,3.725496292114258,3.725492477416992,3.7254891395568848,3.725485324859619,3.7254817485809326,3.725478410720825,3.7254745960235596,3.725471019744873,3.7254672050476074,3.7254638671875,3.725459575653076,3.7254555225372314,3.7254512310028076,3.725447416305542,3.725442886352539,3.725438117980957,3.725432872772217,3.7254273891448975,3.7254226207733154,3.725417137145996,3.725412130355835,3.7254068851470947,3.7254011631011963,3.725395679473877,3.7253904342651367,3.7253847122192383,3.7253785133361816,3.725372791290283,3.7253665924072266,3.725360631942749,3.7253549098968506,3.725348949432373,3.7253429889678955,3.725336790084839,3.7253317832946777,3.7253267765045166,3.7253215312957764,3.725316047668457,3.7253103256225586,3.72530460357666,3.7252988815307617,3.7252931594848633,3.725287437438965,3.7252817153930664,3.725275993347168,3.7252702713012695,3.725264072418213,3.7252583503723145,3.725252628326416,3.7252469062805176,3.725240707397461,3.725233554840088,3.7252283096313477,3.7252228260040283,3.72521710395813,3.7252118587493896,3.7252068519592285,3.7252018451690674,3.725196361541748,3.725191831588745,3.725186824798584,3.725182294845581,3.7251780033111572,3.7251739501953125,3.725170135498047,3.725165843963623,3.7251620292663574,3.72515869140625,3.7251548767089844,3.725151300430298,3.7251479625701904,3.725144386291504,3.7251412868499756,3.7251391410827637,3.7251367568969727,3.725135326385498,3.725132942199707,3.7251315116882324,3.7251298427581787,3.7251288890838623,3.725127696990967,3.7251269817352295,3.725125789642334,3.7251250743865967,3.7251241207122803,3.725123405456543,3.7251229286193848,3.7251226902008057,3.7251226902008057,3.7251222133636475,3.7251222133636475,3.7251222133636475,3.7251226902008057,3.7251229286193848,3.725123405456543,3.7251241207122803,3.7251250743865967,3.725125789642334,3.7251269817352295,3.725127935409546,3.7251291275024414,3.725130796432495,3.7251322269439697,3.7251341342926025,3.7251365184783936,3.7251386642456055,3.7251405715942383,3.7251434326171875,3.7251460552215576,3.725149154663086,3.725152015686035,3.7251551151275635,3.7251577377319336,3.72516131401062,3.7251651287078857,3.725168466567993,3.725172281265259,3.7251760959625244,3.725180149078369,3.7251839637756348,3.7251880168914795,3.725191831588745,3.725196123123169,3.7252004146575928,3.7252044677734375,3.7252087593078613,3.725212812423706,3.72521710395813,3.7252209186553955,3.7252252101898193,3.725229263305664,3.725233316421509,3.7252371311187744,3.72524094581604,3.7252447605133057],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"}]},{"data":[{"marker":{"color":"#636EFA","size":3},"mode":"markers","name":"cluster 0","x":[2.578917980194092,2.578918218612671,2.578918218612671,2.57891845703125,2.57891845703125,2.578918218612671,2.578918218612671,2.578917980194092,2.578917980194092,2.5789175033569336,2.5789172649383545,2.5789170265197754,2.578916311264038,2.57891583442688,2.5789151191711426,2.5789146423339844,2.578914165496826,2.5789132118225098,2.5789127349853516,2.5789120197296143,2.578911304473877,2.5789103507995605,2.578909397125244,2.5789084434509277,2.5789074897766113,2.578906774520874,2.5789058208465576,2.578904867172241,2.578903913497925,2.5789027214050293,2.578901767730713,2.5789008140563965,2.578899621963501,2.5788986682891846,2.578897476196289,2.5788967609405518,2.5788955688476562,2.5788943767547607,2.5788931846618652,2.578892230987549,2.5788910388946533,2.578890085220337,2.5788888931274414,2.578887701034546,2.5788867473602295,2.578885555267334,2.5788843631744385,2.578883647918701,2.5788824558258057,2.57888126373291,2.5788803100585938,2.5788793563842773,2.578878402709961,2.5788774490356445,2.578876495361328,2.5788755416870117,2.5788745880126953,2.578873634338379,2.5788726806640625,2.578871726989746,2.5788707733154297,2.5788698196411133,2.578868865966797,2.5788681507110596,2.578867197036743,2.578866481781006,2.5788657665252686,2.5788650512695312,2.5788638591766357,2.5788631439208984,2.578862428665161,2.578861713409424,2.5788609981536865,2.57886004447937,2.578859329223633,2.5788588523864746,2.5788581371307373,2.578857421875,2.5788567066192627,2.5788562297821045,2.578855276107788,2.578854560852051,2.5788540840148926,2.5788533687591553,2.578852891921997,2.578852415084839,2.5788516998291016,2.5788512229919434,2.578850746154785,2.578850507736206,2.5788495540618896,2.5788493156433105,2.5788486003875732,2.578848361968994,2.578847885131836,2.5788474082946777,2.5788469314575195,2.5788464546203613,2.578845977783203,2.578845739364624,2.578845500946045,2.5788450241088867,2.5788445472717285,2.5788445472717285,2.5788443088531494,2.578843832015991,2.578843832015991,2.578843593597412,2.578843116760254,2.578843116760254,2.578843116760254,2.5788426399230957,2.5788426399230957,2.5788426399230957,2.5788426399230957,2.5788426399230957,2.5788426399230957,2.5788426399230957,2.5788426399230957,2.5788426399230957,2.5788426399230957,2.578843116760254,2.578843116760254,2.578843116760254,2.578843593597412,2.578843593597412,2.578843832015991,2.578843832015991,2.5788443088531494,2.5788445472717285,2.5788447856903076,2.578845262527466,2.578845500946045,2.578845500946045,2.578845739364624,2.5788462162017822,2.5788466930389404,2.5788469314575195,2.5788474082946777,2.578847646713257,2.578848123550415,2.5788486003875732,2.5788488388061523,2.5788493156433105,2.5788495540618896,2.578850030899048,2.578850507736206,2.5788509845733643,2.5788514614105225,2.5788519382476807,2.578852415084839,2.578852653503418,2.5788533687591553,2.5788536071777344,2.5788540840148926,2.5788543224334717,2.57885479927063,2.578855276107788,2.5788557529449463,2.5788562297821045,2.5788564682006836,2.578856945037842,2.578857183456421,2.578857660293579,2.5788581371307373,2.5788583755493164,2.5788588523864746,2.578859329223633,2.578859806060791,2.57886004447937,2.5788605213165283,2.5788609981536865,2.5788614749908447,2.578861951828003,2.578862190246582,2.5788626670837402,2.5788629055023193,2.5788631439208984,2.5788636207580566,2.5788638591766357,2.578864097595215,2.578864574432373,2.5788650512695312,2.5788652896881104,2.5788657665252686,2.5788660049438477,2.5788662433624268,2.578866720199585,2.578866958618164,2.578866958618164,2.578867197036743,2.5788676738739014,2.5788679122924805,2.5788679122924805,2.5788683891296387,2.578868865966797,2.578868865966797,2.578869104385376,2.578869342803955,2.578869581222534,2.5788698196411133,2.5788698196411133,2.5788700580596924,2.5788702964782715,2.5788705348968506,2.5788707733154297,2.5788707733154297,2.5788707733154297,2.5788707733154297,2.578871011734009,2.578871250152588,2.578871250152588,2.578871488571167,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871726989746,2.578871488571167,2.578871488571167,2.578871488571167,2.578871011734009,2.578871011734009,2.578871011734009,2.578871011734009,2.5788707733154297,2.5788707733154297,2.5788705348968506,2.5788702964782715,2.5788700580596924,2.5788698196411133,2.5788698196411133,2.578869581222534,2.578869342803955,2.578869342803955,2.578869104385376,2.578868865966797],"y":[-21.17802619934082,-21.178024291992188,-21.178024291992188,-21.178022384643555,-21.178020477294922,-21.17801856994629,-21.178016662597656,-21.178016662597656,-21.178016662597656,-21.17801284790039,-21.17801284790039,-21.178010940551758,-21.178010940551758,-21.178009033203125,-21.178009033203125,-21.178009033203125,-21.178007125854492,-21.17800521850586,-21.17800521850586,-21.17800521850586,-21.178003311157227,-21.178001403808594,-21.178001403808594,-21.178001403808594,-21.178001403808594,-21.17799949645996,-21.17799949645996,-21.177997589111328,-21.177995681762695,-21.177995681762695,-21.177995681762695,-21.177995681762695,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.17799186706543,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177993774414062,-21.177995681762695,-21.177995681762695,-21.177995681762695,-21.177997589111328,-21.177997589111328,-21.17799949645996,-21.17799949645996,-21.17799949645996,-21.178001403808594,-21.178001403808594,-21.178001403808594,-21.178003311157227,-21.178003311157227,-21.17800521850586,-21.17800521850586,-21.17800521850586,-21.178007125854492,-21.178007125854492,-21.178009033203125,-21.178009033203125,-21.178009033203125,-21.178010940551758,-21.178010940551758,-21.178010940551758,-21.178014755249023,-21.178014755249023,-21.178014755249023,-21.178016662597656,-21.178016662597656,-21.178016662597656,-21.178016662597656,-21.178016662597656,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178022384643555,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.17802619934082,-21.17802619934082,-21.17802619934082,-21.178028106689453,-21.178030014038086,-21.178030014038086,-21.178030014038086,-21.178030014038086,-21.17803192138672,-21.17803192138672,-21.17803192138672,-21.17803382873535,-21.17803382873535,-21.17803382873535,-21.17803382873535,-21.17803382873535,-21.178035736083984,-21.178035736083984,-21.178035736083984,-21.178035736083984,-21.178035736083984,-21.178037643432617,-21.178037643432617,-21.178037643432617,-21.178037643432617,-21.178037643432617,-21.178037643432617,-21.17803955078125,-21.17803955078125,-21.17803955078125,-21.17803955078125,-21.17803955078125,-21.17803955078125,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.178041458129883,-21.17803955078125,-21.17803955078125,-21.17803955078125,-21.17803955078125,-21.17803955078125,-21.17803955078125,-21.17803955078125,-21.178037643432617,-21.178037643432617,-21.178037643432617,-21.178037643432617,-21.178037643432617,-21.178035736083984,-21.178035736083984,-21.178035736083984,-21.178035736083984,-21.178035736083984,-21.17803382873535,-21.17803382873535,-21.17803192138672,-21.17803192138672,-21.17803192138672,-21.17803192138672,-21.17803192138672,-21.17803192138672,-21.17803192138672,-21.178030014038086,-21.178030014038086,-21.178030014038086,-21.178030014038086,-21.178030014038086,-21.178030014038086,-21.178030014038086,-21.178028106689453,-21.178028106689453,-21.17802619934082,-21.17802619934082,-21.17802619934082,-21.17802619934082,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178024291992188,-21.178022384643555,-21.178022384643555,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922,-21.178020477294922],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"#EF553B","size":3},"mode":"markers","name":"cluster 1","x":[11.031108856201172,11.031103134155273,11.031098365783691,11.031094551086426,11.031089782714844,11.031085014343262,11.03108024597168,11.031076431274414,11.031071662902832,11.031067848205566,11.0310640335083,11.031060218811035,11.03105640411377,11.031052589416504,11.031049728393555,11.031046867370605,11.031044006347656,11.03104019165039,11.031037330627441,11.031034469604492,11.03103256225586,11.03102970123291,11.031028747558594,11.031024932861328,11.031023979187012,11.031021118164062,11.03101921081543,11.031017303466797,11.031015396118164,11.031013488769531,11.031012535095215,11.031010627746582,11.031009674072266,11.031007766723633,11.031005859375,11.031005859375,11.031003952026367,11.031002044677734,11.031001091003418,11.031001091003418,11.030999183654785,11.030999183654785,11.030998229980469,11.030998229980469,11.030996322631836,11.030996322631836,11.03099536895752,11.03099536895752,11.030994415283203,11.030994415283203,11.030994415283203,11.030994415283203,11.030994415283203,11.030994415283203,11.030994415283203,11.030994415283203,11.030994415283203,11.030994415283203,11.030994415283203,11.030994415283203,11.03099536895752,11.03099536895752,11.030996322631836,11.030996322631836,11.030996322631836,11.030996322631836,11.030997276306152,11.030998229980469,11.030998229980469,11.030999183654785,11.031000137329102,11.031000137329102,11.031001091003418,11.031002044677734,11.031002044677734,11.03100299835205,11.031003952026367,11.031004905700684,11.031005859375,11.031005859375,11.031007766723633,11.03100872039795,11.031009674072266,11.031009674072266,11.031010627746582,11.031011581420898,11.031013488769531,11.031014442443848,11.031014442443848,11.03101634979248,11.03101634979248,11.031017303466797,11.031017303466797,11.03101921081543,11.031020164489746,11.031021118164062,11.031022071838379,11.031023025512695,11.031023979187012,11.031024932861328,11.031025886535645,11.031026840209961,11.031028747558594,11.031028747558594,11.03102970123291,11.03102970123291,11.031031608581543,11.03103256225586,11.03103256225586,11.031034469604492,11.031034469604492,11.031036376953125,11.031037330627441,11.031037330627441,11.031039237976074,11.03104019165039,11.03104019165039,11.031042098999023,11.03104305267334,11.031044006347656,11.031044006347656,11.031045913696289,11.031046867370605,11.031046867370605,11.031047821044922,11.031047821044922,11.031049728393555,11.031051635742188,11.031051635742188,11.031052589416504,11.031052589416504,11.031054496765137,11.03105640411377,11.03105640411377,11.031057357788086,11.031057357788086,11.031059265136719,11.031059265136719,11.031060218811035,11.031062126159668,11.031063079833984,11.0310640335083,11.0310640335083,11.031064987182617,11.031065940856934,11.03106689453125,11.031067848205566,11.031067848205566,11.031068801879883,11.031070709228516,11.031071662902832,11.031071662902832,11.031072616577148,11.031072616577148,11.031073570251465,11.031074523925781,11.031075477600098,11.031075477600098,11.031076431274414,11.031076431274414,11.03107738494873,11.031078338623047,11.031079292297363,11.031079292297363,11.031079292297363,11.03108024597168,11.03108024597168,11.031081199645996,11.031081199645996,11.031081199645996,11.031082153320312,11.031082153320312,11.031083106994629,11.031083106994629,11.031083106994629,11.031083106994629,11.031083106994629,11.031084060668945,11.031084060668945,11.031084060668945,11.031084060668945,11.031084060668945,11.031084060668945,11.031084060668945,11.031084060668945,11.031084060668945,11.031084060668945,11.031084060668945,11.031083106994629,11.031083106994629,11.031083106994629,11.031083106994629,11.031083106994629,11.031083106994629,11.031083106994629,11.031082153320312,11.031082153320312,11.031082153320312,11.03108024597168,11.03108024597168,11.031079292297363,11.031079292297363,11.031078338623047,11.031078338623047,11.03107738494873,11.031076431274414,11.031075477600098,11.031075477600098,11.031073570251465,11.031072616577148,11.031071662902832,11.031071662902832,11.0310697555542,11.0310697555542,11.031067848205566,11.031067848205566,11.031065940856934,11.031064987182617,11.0310640335083,11.031063079833984,11.031063079833984,11.031061172485352,11.031060218811035,11.031060218811035,11.031059265136719,11.031058311462402,11.031057357788086,11.03105640411377,11.03105640411377,11.031055450439453,11.031054496765137,11.031054496765137,11.031052589416504,11.031052589416504,11.031052589416504,11.031051635742188,11.031050682067871,11.031050682067871,11.031049728393555,11.031049728393555,11.031047821044922,11.031047821044922,11.031047821044922,11.031047821044922,11.031047821044922,11.031046867370605,11.031046867370605,11.031046867370605,11.031044960021973,11.031044960021973],"y":[10.844741821289062,10.844743728637695,10.844746589660645,10.844747543334961,10.844749450683594,10.844751358032227,10.844752311706543,10.844754219055176,10.844755172729492,10.844757080078125,10.844758987426758,10.844759941101074,10.844762802124023,10.84476375579834,10.844765663146973,10.844766616821289,10.844768524169922,10.844770431518555,10.844771385192871,10.844773292541504,10.84477424621582,10.844775199890137,10.84477710723877,10.844778060913086,10.844779968261719,10.844781875610352,10.844782829284668,10.844782829284668,10.8447847366333,10.844785690307617,10.844786643981934,10.844788551330566,10.844789505004883,10.8447904586792,10.844792366027832,10.844793319702148,10.844794273376465,10.844796180725098,10.844797134399414,10.84479808807373,10.844799041748047,10.844799995422363,10.84480094909668,10.844802856445312,10.844803810119629,10.844804763793945,10.844805717468262,10.844806671142578,10.844807624816895,10.844808578491211,10.844810485839844,10.844810485839844,10.844812393188477,10.844813346862793,10.84481430053711,10.844815254211426,10.844816207885742,10.844817161560059,10.844817161560059,10.844818115234375,10.844819068908691,10.844820022583008,10.844820976257324,10.844820976257324,10.84482192993164,10.844822883605957,10.844822883605957,10.84482479095459,10.84482479095459,10.84482479095459,10.84482479095459,10.844825744628906,10.844826698303223,10.844826698303223,10.844827651977539,10.844828605651855,10.844828605651855,10.844828605651855,10.844828605651855,10.844828605651855,10.844830513000488,10.844830513000488,10.844830513000488,10.844831466674805,10.844831466674805,10.844831466674805,10.844831466674805,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844833374023438,10.844833374023438,10.844833374023438,10.844833374023438,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844832420349121,10.844831466674805,10.844831466674805,10.844831466674805,10.844831466674805,10.844830513000488,10.844830513000488,10.844829559326172,10.844828605651855,10.844828605651855,10.844828605651855,10.844828605651855,10.844828605651855,10.844827651977539,10.844827651977539,10.844826698303223,10.844825744628906,10.84482479095459,10.84482479095459,10.84482479095459,10.844823837280273,10.844822883605957,10.84482192993164,10.844820976257324,10.844820976257324,10.844820022583008,10.844819068908691,10.844818115234375,10.844818115234375,10.844818115234375,10.844817161560059,10.844817161560059,10.844815254211426,10.844813346862793,10.844813346862793,10.844812393188477,10.84481143951416,10.844810485839844,10.844809532165527,10.844808578491211,10.844808578491211,10.844807624816895,10.844806671142578,10.844805717468262,10.844804763793945,10.844804763793945,10.844802856445312,10.844801902770996,10.84480094909668,10.84480094909668,10.844799995422363,10.844799041748047,10.84479808807373,10.844797134399414,10.844797134399414,10.844796180725098,10.844795227050781,10.844794273376465,10.844793319702148,10.844793319702148,10.844793319702148,10.844792366027832,10.844791412353516,10.8447904586792,10.844789505004883,10.844789505004883,10.844789505004883,10.844789505004883,10.84478759765625,10.84478759765625,10.844785690307617,10.844785690307617,10.844785690307617,10.844785690307617,10.8447847366333,10.844783782958984,10.844783782958984,10.844783782958984,10.844782829284668,10.844782829284668,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844781875610352,10.844782829284668,10.844783782958984,10.8447847366333,10.8447847366333,10.8447847366333,10.844785690307617,10.844785690307617,10.844785690307617,10.84478759765625,10.84478759765625,10.844789505004883,10.844789505004883,10.8447904586792,10.8447904586792,10.8447904586792,10.844791412353516,10.844792366027832,10.844792366027832,10.844793319702148,10.844793319702148,10.844794273376465,10.844794273376465,10.844794273376465,10.844795227050781,10.844795227050781,10.844796180725098,10.844797134399414,10.844797134399414,10.844797134399414,10.844797134399414,10.844797134399414,10.84479808807373,10.84479808807373,10.84479808807373,10.844799041748047,10.844799995422363,10.84480094909668,10.84480094909668,10.84480094909668,10.84480094909668,10.84480094909668,10.844801902770996,10.844802856445312,10.844802856445312,10.844802856445312,10.844802856445312],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"#00CC96","size":3},"mode":"markers","name":"cluster 2","x":[-18.722532272338867,-18.7225284576416,-18.722524642944336,-18.722524642944336,-18.722524642944336,-18.722522735595703,-18.722518920898438,-18.722518920898438,-18.722515106201172,-18.72251319885254,-18.722511291503906,-18.722509384155273,-18.72250747680664,-18.722503662109375,-18.722503662109375,-18.72249984741211,-18.72249984741211,-18.722497940063477,-18.722497940063477,-18.72249412536621,-18.722492218017578,-18.722492218017578,-18.722488403320312,-18.722488403320312,-18.722488403320312,-18.722484588623047,-18.722484588623047,-18.722482681274414,-18.72247886657715,-18.72247886657715,-18.722476959228516,-18.722476959228516,-18.722476959228516,-18.72247314453125,-18.72247314453125,-18.72247314453125,-18.722471237182617,-18.722469329833984,-18.722469329833984,-18.722469329833984,-18.72246742248535,-18.72246742248535,-18.72246742248535,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722461700439453,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.722463607788086,-18.72246742248535,-18.72246742248535,-18.72246742248535,-18.722469329833984,-18.722469329833984,-18.722469329833984,-18.722469329833984,-18.722469329833984,-18.72247314453125,-18.72247314453125,-18.72247314453125,-18.72247314453125,-18.72247314453125,-18.72247314453125,-18.72247314453125,-18.722475051879883,-18.722476959228516,-18.722476959228516,-18.722476959228516,-18.722476959228516,-18.722476959228516,-18.72247886657715,-18.72247886657715,-18.72247886657715,-18.72247886657715,-18.72247886657715,-18.72247886657715,-18.72248077392578,-18.722482681274414,-18.722482681274414,-18.722482681274414,-18.722482681274414,-18.722484588623047,-18.722484588623047,-18.722484588623047,-18.722484588623047,-18.72248649597168,-18.722488403320312,-18.722488403320312,-18.722488403320312,-18.722488403320312,-18.722488403320312,-18.722488403320312,-18.722488403320312,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.72249412536621,-18.72249412536621,-18.72249412536621,-18.722496032714844,-18.722496032714844,-18.722497940063477,-18.722497940063477,-18.722497940063477,-18.722497940063477,-18.722497940063477,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722505569458008,-18.722505569458008,-18.722505569458008,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.722509384155273,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.72250747680664,-18.722505569458008,-18.722505569458008,-18.722505569458008,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722503662109375,-18.722501754760742,-18.722501754760742,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.72249984741211,-18.722497940063477,-18.722497940063477,-18.722497940063477,-18.722497940063477,-18.722496032714844,-18.722496032714844,-18.722496032714844,-18.722496032714844,-18.722496032714844,-18.72249412536621,-18.72249412536621,-18.72249412536621,-18.72249412536621,-18.72249412536621,-18.72249412536621,-18.72249412536621,-18.72249412536621,-18.72249412536621,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722492218017578,-18.722490310668945,-18.722490310668945],"y":[-5.475937366485596,-5.47593879699707,-5.475940227508545,-5.4759416580200195,-5.475942611694336,-5.4759440422058105,-5.475945949554443,-5.475946426391602,-5.475947856903076,-5.475949764251709,-5.475950717926025,-5.4759521484375,-5.475953578948975,-5.475954055786133,-5.475955486297607,-5.475956439971924,-5.47595739364624,-5.475959300994873,-5.475959777832031,-5.475960731506348,-5.475961685180664,-5.4759626388549805,-5.475963592529297,-5.475964069366455,-5.4759650230407715,-5.47596549987793,-5.475966453552246,-5.4759674072265625,-5.4759674072265625,-5.475968360900879,-5.475968837738037,-5.475969314575195,-5.475969314575195,-5.4759697914123535,-5.475970268249512,-5.47597074508667,-5.475971221923828,-5.475971221923828,-5.475971221923828,-5.475971221923828,-5.475971698760986,-5.475971698760986,-5.475971698760986,-5.475971698760986,-5.475971698760986,-5.475971698760986,-5.475971221923828,-5.475971221923828,-5.475971221923828,-5.475971221923828,-5.475971221923828,-5.475970268249512,-5.475970268249512,-5.4759697914123535,-5.4759697914123535,-5.475969314575195,-5.475969314575195,-5.475968837738037,-5.475967884063721,-5.4759674072265625,-5.4759674072265625,-5.475966930389404,-5.475966453552246,-5.475965976715088,-5.47596549987793,-5.4759650230407715,-5.475964069366455,-5.475963592529297,-5.475963115692139,-5.475963115692139,-5.475962162017822,-5.475961685180664,-5.475961208343506,-5.475960731506348,-5.4759602546691895,-5.475959777832031,-5.475959300994873,-5.475958824157715,-5.475957870483398,-5.47595739364624,-5.475956916809082,-5.475956439971924,-5.475955486297607,-5.475955486297607,-5.475955009460449,-5.475954055786133,-5.475954055786133,-5.475953578948975,-5.475952625274658,-5.475951671600342,-5.475951671600342,-5.475951194763184,-5.475950717926025,-5.475950241088867,-5.475949764251709,-5.475949287414551,-5.475948810577393,-5.475947856903076,-5.475947380065918,-5.475947380065918,-5.475946426391602,-5.475945949554443,-5.475945472717285,-5.475944995880127,-5.475944519042969,-5.4759440422058105,-5.475943565368652,-5.475943088531494,-5.475942611694336,-5.475942134857178,-5.475941181182861,-5.475940227508545,-5.475940227508545,-5.475939750671387,-5.47593879699707,-5.475938320159912,-5.475938320159912,-5.475937366485596,-5.475936412811279,-5.475935935974121,-5.475935935974121,-5.475935935974121,-5.475934982299805,-5.4759345054626465,-5.475934028625488,-5.47593355178833,-5.475932598114014,-5.475932598114014,-5.4759321212768555,-5.475931644439697,-5.475931167602539,-5.475930690765381,-5.475930690765381,-5.4759297370910645,-5.4759297370910645,-5.475928783416748,-5.475928783416748,-5.47592830657959,-5.47592830657959,-5.475927352905273,-5.475927352905273,-5.475926876068115,-5.475926399230957,-5.475926399230957,-5.475925922393799,-5.475925445556641,-5.475925445556641,-5.475924968719482,-5.475924968719482,-5.475924491882324,-5.475924491882324,-5.475924491882324,-5.475924491882324,-5.475924015045166,-5.475924015045166,-5.475924015045166,-5.475924015045166,-5.475924015045166,-5.475923538208008,-5.475923538208008,-5.475923538208008,-5.475923538208008,-5.475923538208008,-5.475923538208008,-5.475923538208008,-5.475923538208008,-5.475924015045166,-5.475924015045166,-5.475924015045166,-5.475924015045166,-5.475924491882324,-5.475924491882324,-5.475924491882324,-5.475924491882324,-5.475925445556641,-5.475925445556641,-5.475925922393799,-5.475925922393799,-5.475925922393799,-5.475926399230957,-5.475926399230957,-5.475926876068115,-5.475927352905273,-5.475927829742432,-5.47592830657959,-5.475928783416748,-5.475928783416748,-5.475929260253906,-5.4759297370910645,-5.475930213928223,-5.475930690765381,-5.475930690765381,-5.475931167602539,-5.475931644439697,-5.4759321212768555,-5.475932598114014,-5.475932598114014,-5.475933074951172,-5.47593355178833,-5.475934028625488,-5.4759345054626465,-5.4759345054626465,-5.475934982299805,-5.475935459136963,-5.475935935974121,-5.475936412811279,-5.475936412811279,-5.4759368896484375,-5.475937366485596,-5.475937843322754,-5.475938320159912,-5.475938320159912,-5.47593879699707,-5.47593879699707,-5.4759392738342285,-5.475939750671387,-5.475940227508545,-5.475940227508545,-5.475940704345703,-5.475940704345703,-5.475941181182861,-5.475941181182861,-5.475941181182861,-5.475942134857178,-5.475942134857178,-5.475942134857178,-5.475942134857178,-5.475942134857178,-5.475942134857178,-5.475942611694336,-5.475942611694336,-5.475942611694336,-5.475943088531494,-5.475943088531494,-5.4759440422058105,-5.4759440422058105,-5.4759440422058105,-5.4759440422058105,-5.4759440422058105,-5.4759440422058105,-5.4759440422058105,-5.4759440422058105,-5.4759440422058105,-5.475944519042969,-5.475944995880127,-5.475944995880127,-5.475944995880127,-5.475944995880127,-5.475944995880127,-5.475944995880127],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"#AB63FA","size":3},"mode":"markers","name":"cluster 3","x":[-20.593891143798828,-20.59389305114746,-20.59389305114746,-20.59389305114746,-20.59389305114746,-20.593894958496094,-20.593894958496094,-20.593894958496094,-20.593896865844727,-20.593896865844727,-20.59389877319336,-20.59389877319336,-20.593900680541992,-20.593900680541992,-20.593900680541992,-20.593902587890625,-20.593902587890625,-20.593904495239258,-20.59390640258789,-20.593908309936523,-20.593908309936523,-20.593910217285156,-20.59391212463379,-20.59391212463379,-20.593914031982422,-20.593914031982422,-20.593915939331055,-20.593917846679688,-20.593917846679688,-20.593921661376953,-20.593923568725586,-20.593923568725586,-20.59392547607422,-20.59392547607422,-20.59392547607422,-20.593929290771484,-20.593929290771484,-20.593931198120117,-20.593935012817383,-20.593935012817383,-20.59393882751465,-20.59393882751465,-20.59393882751465,-20.59394073486328,-20.59394073486328,-20.593944549560547,-20.593944549560547,-20.59394645690918,-20.59394645690918,-20.593950271606445,-20.593950271606445,-20.59395408630371,-20.59395408630371,-20.593955993652344,-20.593955993652344,-20.593957901000977,-20.59395980834961,-20.593961715698242,-20.593961715698242,-20.593961715698242,-20.593963623046875,-20.593965530395508,-20.59396743774414,-20.593969345092773,-20.593969345092773,-20.593971252441406,-20.59397315979004,-20.59397315979004,-20.593975067138672,-20.593975067138672,-20.593975067138672,-20.593976974487305,-20.593976974487305,-20.593976974487305,-20.593978881835938,-20.59398078918457,-20.593982696533203,-20.593982696533203,-20.593984603881836,-20.593984603881836,-20.593984603881836,-20.59398651123047,-20.59398651123047,-20.59398651123047,-20.59398651123047,-20.59398651123047,-20.59398651123047,-20.5939884185791,-20.5939884185791,-20.593990325927734,-20.593990325927734,-20.593990325927734,-20.593990325927734,-20.593990325927734,-20.593992233276367,-20.593992233276367,-20.593994140625,-20.593994140625,-20.593994140625,-20.593994140625,-20.593994140625,-20.593994140625,-20.593994140625,-20.593994140625,-20.593994140625,-20.593994140625,-20.593994140625,-20.593992233276367,-20.593992233276367,-20.593992233276367,-20.593990325927734,-20.593990325927734,-20.593990325927734,-20.593990325927734,-20.593990325927734,-20.593990325927734,-20.5939884185791,-20.59398651123047,-20.59398651123047,-20.59398651123047,-20.59398651123047,-20.59398651123047,-20.59398651123047,-20.59398651123047,-20.59398651123047,-20.593984603881836,-20.593982696533203,-20.593982696533203,-20.593982696533203,-20.59398078918457,-20.59398078918457,-20.59398078918457,-20.593978881835938,-20.593978881835938,-20.593976974487305,-20.593976974487305,-20.593976974487305,-20.593975067138672,-20.593975067138672,-20.593975067138672,-20.593975067138672,-20.593975067138672,-20.593975067138672,-20.593971252441406,-20.593971252441406,-20.593971252441406,-20.593969345092773,-20.593969345092773,-20.593969345092773,-20.593969345092773,-20.593969345092773,-20.593965530395508,-20.593965530395508,-20.593965530395508,-20.593963623046875,-20.593963623046875,-20.593961715698242,-20.593961715698242,-20.593961715698242,-20.593961715698242,-20.593961715698242,-20.59395980834961,-20.593957901000977,-20.593957901000977,-20.593957901000977,-20.593957901000977,-20.593957901000977,-20.593955993652344,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.593952178955078,-20.593952178955078,-20.593952178955078,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593948364257812,-20.593948364257812,-20.593948364257812,-20.593948364257812,-20.593948364257812,-20.59394645690918,-20.59394645690918,-20.59394645690918,-20.59394645690918,-20.59394645690918,-20.59394645690918,-20.59394645690918,-20.59394645690918,-20.59394645690918,-20.59394645690918,-20.59394645690918,-20.59394645690918,-20.593948364257812,-20.593948364257812,-20.593948364257812,-20.593948364257812,-20.593948364257812,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593950271606445,-20.593952178955078,-20.593952178955078,-20.593952178955078,-20.593952178955078,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.59395408630371,-20.593955993652344,-20.593955993652344,-20.593955993652344,-20.593955993652344,-20.593955993652344,-20.593955993652344,-20.593955993652344,-20.593955993652344,-20.593955993652344,-20.593957901000977,-20.593957901000977],"y":[9.09961223602295,9.099610328674316,9.099608421325684,9.099607467651367,9.099604606628418,9.099602699279785,9.099600791931152,9.099599838256836,9.099597930908203,9.099595069885254,9.099593162536621,9.099592208862305,9.099590301513672,9.099589347839355,9.099587440490723,9.09958553314209,9.099584579467773,9.09958267211914,9.099581718444824,9.099579811096191,9.099577903747559,9.099577903747559,9.099576950073242,9.09957504272461,9.099573135375977,9.09957218170166,9.099571228027344,9.099570274353027,9.099569320678711,9.099568367004395,9.099567413330078,9.099567413330078,9.099565505981445,9.099565505981445,9.099565505981445,9.099564552307129,9.099564552307129,9.099563598632812,9.099563598632812,9.099562644958496,9.099562644958496,9.099562644958496,9.099562644958496,9.099562644958496,9.099562644958496,9.099562644958496,9.099562644958496,9.099562644958496,9.099562644958496,9.099562644958496,9.099562644958496,9.099563598632812,9.099563598632812,9.099564552307129,9.099564552307129,9.099564552307129,9.099565505981445,9.099565505981445,9.099565505981445,9.099566459655762,9.099566459655762,9.099567413330078,9.099568367004395,9.099569320678711,9.099569320678711,9.099570274353027,9.099571228027344,9.09957218170166,9.09957218170166,9.099573135375977,9.099573135375977,9.099574089050293,9.09957504272461,9.099575996398926,9.099576950073242,9.099576950073242,9.099577903747559,9.099577903747559,9.099579811096191,9.099579811096191,9.099581718444824,9.099581718444824,9.09958267211914,9.099584579467773,9.09958553314209,9.09958553314209,9.099586486816406,9.099587440490723,9.099588394165039,9.099589347839355,9.099589347839355,9.099590301513672,9.099591255187988,9.099592208862305,9.099593162536621,9.099593162536621,9.099594116210938,9.099595069885254,9.099595069885254,9.099595069885254,9.099596977233887,9.099596977233887,9.099597930908203,9.099597930908203,9.099597930908203,9.099599838256836,9.099599838256836,9.099600791931152,9.099600791931152,9.099601745605469,9.099602699279785,9.099602699279785,9.099603652954102,9.099604606628418,9.099604606628418,9.099605560302734,9.099605560302734,9.09960651397705,9.09960651397705,9.09960651397705,9.099607467651367,9.099608421325684,9.099608421325684,9.099608421325684,9.099609375,9.099610328674316,9.099610328674316,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.099613189697266,9.099613189697266,9.099615097045898,9.099615097045898,9.099615097045898,9.099615097045898,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099616050720215,9.099615097045898,9.099615097045898,9.099615097045898,9.099615097045898,9.099615097045898,9.099615097045898,9.099615097045898,9.099615097045898,9.099613189697266,9.099613189697266,9.099613189697266,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.09961223602295,9.099610328674316,9.099610328674316,9.099610328674316,9.099609375,9.099608421325684,9.099608421325684,9.099608421325684,9.099608421325684,9.099607467651367,9.099607467651367,9.099607467651367,9.09960651397705,9.09960651397705,9.09960651397705,9.099605560302734,9.099605560302734,9.099605560302734,9.099604606628418,9.099604606628418,9.099604606628418,9.099604606628418,9.099604606628418,9.099603652954102,9.099603652954102,9.099602699279785,9.099602699279785,9.099602699279785,9.099602699279785,9.099602699279785,9.099600791931152,9.099600791931152,9.099600791931152,9.099600791931152,9.099600791931152,9.099599838256836,9.099599838256836,9.099599838256836,9.099599838256836,9.099599838256836,9.099599838256836,9.099597930908203,9.099597930908203,9.099597930908203,9.099597930908203,9.099597930908203,9.099597930908203,9.099597930908203,9.099597930908203,9.099596977233887,9.099596977233887,9.099596977233887,9.099596977233887,9.099596977233887,9.099596977233887,9.099596977233887,9.099596977233887,9.099596977233887,9.099596977233887,9.099596977233887],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"#FFA15A","size":3},"mode":"markers","name":"cluster 4","x":[-9.634350776672363,-9.63435173034668,-9.63435173034668,-9.634353637695312,-9.634354591369629,-9.634354591369629,-9.634355545043945,-9.634355545043945,-9.634356498718262,-9.634358406066895,-9.634358406066895,-9.634359359741211,-9.634360313415527,-9.634361267089844,-9.63436222076416,-9.63436222076416,-9.634363174438477,-9.63436508178711,-9.63436508178711,-9.634366035461426,-9.634366989135742,-9.634368896484375,-9.634369850158691,-9.634369850158691,-9.634370803833008,-9.634371757507324,-9.63437271118164,-9.634373664855957,-9.634374618530273,-9.63437557220459,-9.634376525878906,-9.634377479553223,-9.634377479553223,-9.634378433227539,-9.634379386901855,-9.634380340576172,-9.634381294250488,-9.634381294250488,-9.634382247924805,-9.634383201599121,-9.634384155273438,-9.634385108947754,-9.634385108947754,-9.63438606262207,-9.634387016296387,-9.634387969970703,-9.63438892364502,-9.63438892364502,-9.634389877319336,-9.634390830993652,-9.634391784667969,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634393692016602,-9.634394645690918,-9.634395599365234,-9.63439655303955,-9.63439655303955,-9.634397506713867,-9.634398460388184,-9.634398460388184,-9.634398460388184,-9.634400367736816,-9.634400367736816,-9.634401321411133,-9.634401321411133,-9.634403228759766,-9.634403228759766,-9.634403228759766,-9.634404182434082,-9.634404182434082,-9.634405136108398,-9.634405136108398,-9.634405136108398,-9.634406089782715,-9.634406089782715,-9.634407997131348,-9.634407997131348,-9.634407997131348,-9.634407997131348,-9.634408950805664,-9.634408950805664,-9.63440990447998,-9.634410858154297,-9.634410858154297,-9.634410858154297,-9.634410858154297,-9.634411811828613,-9.634411811828613,-9.634411811828613,-9.634411811828613,-9.634411811828613,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.63441276550293,-9.634411811828613,-9.634411811828613,-9.634411811828613,-9.634411811828613,-9.634411811828613,-9.634410858154297,-9.634410858154297,-9.634410858154297,-9.634410858154297,-9.634410858154297,-9.634410858154297,-9.63440990447998,-9.63440990447998,-9.63440990447998,-9.634408950805664,-9.634408950805664,-9.634408950805664,-9.634407997131348,-9.634407997131348,-9.634407997131348,-9.634407997131348,-9.634407997131348,-9.634407997131348,-9.634407043457031,-9.634406089782715,-9.634405136108398,-9.634405136108398,-9.634404182434082,-9.634404182434082,-9.634404182434082,-9.634403228759766,-9.634403228759766,-9.634403228759766,-9.634401321411133,-9.634401321411133,-9.634400367736816,-9.634400367736816,-9.634400367736816,-9.634400367736816,-9.634400367736816,-9.634398460388184,-9.634398460388184,-9.634398460388184,-9.634397506713867,-9.63439655303955,-9.63439655303955,-9.63439655303955,-9.63439655303955,-9.634395599365234,-9.634395599365234,-9.634395599365234,-9.634394645690918,-9.634393692016602,-9.634393692016602,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634391784667969,-9.634390830993652,-9.634390830993652,-9.634390830993652,-9.634390830993652,-9.634390830993652,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.63438606262207,-9.63438606262207,-9.63438606262207,-9.63438606262207,-9.63438606262207,-9.63438606262207,-9.63438606262207,-9.63438606262207,-9.63438606262207,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.634387969970703,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.63438892364502,-9.634389877319336,-9.634389877319336,-9.634390830993652,-9.634390830993652,-9.634390830993652,-9.634390830993652,-9.634390830993652,-9.634390830993652,-9.634390830993652,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634392738342285,-9.634393692016602,-9.634393692016602,-9.634393692016602,-9.634393692016602],"y":[24.50691032409668,24.50691032409668,24.506906509399414,24.506906509399414,24.50690460205078,24.50690460205078,24.50690460205078,24.50690269470215,24.506900787353516,24.506900787353516,24.506898880004883,24.50689697265625,24.50689697265625,24.50689697265625,24.50689697265625,24.506895065307617,24.506895065307617,24.506893157958984,24.506893157958984,24.506893157958984,24.50689125061035,24.50688934326172,24.50688934326172,24.50688934326172,24.50688934326172,24.506887435913086,24.506887435913086,24.506885528564453,24.506885528564453,24.506885528564453,24.506881713867188,24.506881713867188,24.506881713867188,24.506881713867188,24.506881713867188,24.506879806518555,24.506877899169922,24.50687599182129,24.506874084472656,24.506874084472656,24.506874084472656,24.506874084472656,24.506874084472656,24.50687026977539,24.50687026977539,24.506868362426758,24.506868362426758,24.506866455078125,24.506866455078125,24.506864547729492,24.50686264038086,24.50686264038086,24.506860733032227,24.506860733032227,24.506860733032227,24.506858825683594,24.506858825683594,24.50685691833496,24.50685691833496,24.506855010986328,24.506853103637695,24.506851196289062,24.506851196289062,24.50684928894043,24.50684928894043,24.50684928894043,24.50684928894043,24.506847381591797,24.506845474243164,24.506845474243164,24.50684356689453,24.50684356689453,24.5068416595459,24.506839752197266,24.506839752197266,24.506839752197266,24.506839752197266,24.506837844848633,24.5068359375,24.5068359375,24.506834030151367,24.506834030151367,24.506834030151367,24.506832122802734,24.506832122802734,24.506832122802734,24.5068302154541,24.5068302154541,24.50682830810547,24.506826400756836,24.506826400756836,24.506826400756836,24.506826400756836,24.506826400756836,24.506824493408203,24.506824493408203,24.506824493408203,24.506824493408203,24.506820678710938,24.506820678710938,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506818771362305,24.506820678710938,24.50682258605957,24.506824493408203,24.506824493408203,24.506824493408203,24.506824493408203,24.506824493408203,24.506826400756836,24.506826400756836,24.506826400756836,24.50682830810547,24.50682830810547,24.506832122802734,24.506832122802734,24.506832122802734,24.506832122802734,24.506834030151367,24.506834030151367,24.5068359375,24.5068359375,24.5068359375,24.506837844848633,24.506837844848633,24.506839752197266,24.5068416595459,24.5068416595459,24.5068416595459,24.50684356689453,24.50684356689453,24.506845474243164,24.506845474243164,24.506845474243164,24.50684928894043,24.50684928894043,24.50684928894043,24.50684928894043,24.50684928894043,24.506851196289062,24.506851196289062,24.506851196289062,24.506853103637695,24.506853103637695,24.506855010986328,24.50685691833496,24.50685691833496,24.50685691833496,24.50685691833496,24.50685691833496,24.506858825683594,24.506858825683594,24.506858825683594,24.506858825683594,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.50686264038086,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506860733032227,24.506858825683594,24.506858825683594,24.506858825683594,24.506858825683594,24.506858825683594,24.506858825683594,24.506858825683594,24.50685691833496,24.50685691833496,24.50685691833496,24.50685691833496,24.50685691833496,24.50685691833496,24.50685691833496,24.50685691833496,24.50685691833496,24.506855010986328,24.506855010986328,24.506855010986328,24.506855010986328,24.506855010986328,24.506853103637695,24.506851196289062,24.506851196289062],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"#19D3F3","size":3},"mode":"markers","name":"cluster 5","x":[24.875041961669922,24.87504005432129,24.875038146972656,24.875038146972656,24.875036239624023,24.87503433227539,24.875032424926758,24.875030517578125,24.875030517578125,24.875030517578125,24.875028610229492,24.87502670288086,24.875024795532227,24.875022888183594,24.875022888183594,24.875022888183594,24.87502098083496,24.875019073486328,24.875017166137695,24.875015258789062,24.875015258789062,24.87501335144043,24.87501335144043,24.875009536743164,24.875009536743164,24.87500762939453,24.87500762939453,24.87500762939453,24.8750057220459,24.875003814697266,24.875001907348633,24.875,24.875,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.8749942779541,24.8749942779541,24.8749942779541,24.87499237060547,24.87499237060547,24.874990463256836,24.874990463256836,24.874990463256836,24.874988555908203,24.874988555908203,24.874988555908203,24.874988555908203,24.87498664855957,24.874984741210938,24.874984741210938,24.874984741210938,24.874984741210938,24.874982833862305,24.874982833862305,24.874982833862305,24.874982833862305,24.874982833862305,24.874980926513672,24.874980926513672,24.874980926513672,24.87497901916504,24.87497901916504,24.87497901916504,24.87497901916504,24.874977111816406,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.874975204467773,24.87497901916504,24.87497901916504,24.87497901916504,24.874980926513672,24.874980926513672,24.874982833862305,24.874982833862305,24.874982833862305,24.874982833862305,24.874982833862305,24.874982833862305,24.874982833862305,24.874984741210938,24.874984741210938,24.874984741210938,24.87498664855957,24.874988555908203,24.874988555908203,24.874988555908203,24.874988555908203,24.874990463256836,24.874990463256836,24.874990463256836,24.87499237060547,24.87499237060547,24.8749942779541,24.8749942779541,24.8749942779541,24.8749942779541,24.874996185302734,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.875,24.875,24.875,24.875,24.875003814697266,24.875003814697266,24.875003814697266,24.8750057220459,24.8750057220459,24.8750057220459,24.8750057220459,24.8750057220459,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.875009536743164,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.87500762939453,24.8750057220459,24.8750057220459,24.875003814697266,24.875003814697266,24.875003814697266,24.875003814697266,24.875003814697266,24.875001907348633,24.875001907348633,24.875001907348633,24.875001907348633,24.875001907348633,24.875,24.875,24.875,24.875,24.875,24.875,24.875,24.875,24.875,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874998092651367,24.874996185302734,24.874996185302734,24.874996185302734,24.874996185302734],"y":[3.7252485752105713,3.725252389907837,3.7252562046051025,3.72525954246521,3.7252631187438965,3.725266456604004,3.7252700328826904,3.7252728939056396,3.725275993347168,3.7252790927886963,3.7252817153930664,3.7252848148345947,3.725287437438965,3.725289821624756,3.725292444229126,3.725295066833496,3.725297451019287,3.725299835205078,3.725301742553711,3.7253036499023438,3.7253055572509766,3.7253074645996094,3.725308895111084,3.7253105640411377,3.7253119945526123,3.725313425064087,3.7253146171569824,3.725316286087036,3.7253172397613525,3.725318431854248,3.7253196239471436,3.725320339202881,3.7253215312957764,3.725322723388672,3.725323438644409,3.7253241539001465,3.7253246307373047,3.725325107574463,3.7253258228302,3.7253265380859375,3.7253265380859375,3.725327253341675,3.725327253341675,3.725327253341675,3.725327730178833,3.725327968597412,3.725327968597412,3.725327968597412,3.725327968597412,3.725327968597412,3.725327730178833,3.725327730178833,3.725327253341675,3.725327253341675,3.725327253341675,3.7253265380859375,3.7253265380859375,3.7253265380859375,3.7253258228302,3.725325107574463,3.725325107574463,3.7253241539001465,3.725323438644409,3.72532320022583,3.7253222465515137,3.7253220081329346,3.725321054458618,3.725320339202881,3.7253196239471436,3.725318431854248,3.7253177165985107,3.7253170013427734,3.725315809249878,3.7253150939941406,3.725313901901245,3.7253127098083496,3.7253119945526123,3.725310802459717,3.7253096103668213,3.725308895111084,3.7253074645996094,3.725306749343872,3.7253057956695557,3.72530460357666,3.7253036499023438,3.7253026962280273,3.725301742553711,3.7253005504608154,3.72529935836792,3.7252981662750244,3.725297451019287,3.7252960205078125,3.725295066833496,3.725294351577759,3.725292921066284,3.725292205810547,3.725290536880493,3.725289821624756,3.7252886295318604,3.725287914276123,3.7252867221832275,3.7252860069274902,3.7252848148345947,3.725283622741699,3.725282907485962,3.7252817153930664,3.725280523300171,3.7252798080444336,3.7252790927886963,3.725278377532959,3.7252771854400635,3.725275993347168,3.7252752780914307,3.725274085998535,3.7252728939056396,3.7252721786499023,3.725271463394165,3.7252707481384277,3.7252700328826904,3.725269079208374,3.7252676486968994,3.725266933441162,3.7252659797668457,3.7252652645111084,3.725264549255371,3.725263833999634,3.7252631187438965,3.72526216506958,3.7252614498138428,3.7252607345581055,3.725260019302368,3.725259304046631,3.7252583503723145,3.7252581119537354,3.725257396697998,3.72525691986084,3.7252562046051025,3.7252554893493652,3.725254535675049,3.7252542972564697,3.7252538204193115,3.725253105163574,3.725252628326416,3.725252389907837,3.7252516746520996,3.7252516746520996,3.725250720977783,3.725250720977783,3.725250005722046,3.725250005722046,3.7252495288848877,3.7252492904663086,3.7252488136291504,3.7252485752105713,3.725248098373413,3.725248098373413,3.725247621536255,3.725247621536255,3.725247621536255,3.725247621536255,3.7252469062805176,3.7252469062805176,3.7252469062805176,3.7252469062805176,3.7252469062805176,3.7252469062805176,3.7252469062805176,3.7252469062805176,3.725247383117676,3.725247621536255,3.725247621536255,3.725247621536255,3.725248098373413,3.725248098373413,3.7252485752105713,3.7252485752105713,3.7252485752105713,3.7252492904663086,3.7252492904663086,3.7252492904663086,3.7252495288848877,3.725250005722046,3.725250482559204,3.725250720977783,3.7252511978149414,3.7252516746520996,3.7252519130706787,3.725252389907837,3.725253105163574,3.7252535820007324,3.7252538204193115,3.725254535675049,3.725254535675049,3.7252554893493652,3.7252554893493652,3.7252562046051025,3.72525691986084,3.725257635116577,3.7252581119537354,3.7252583503723145,3.725259304046631,3.72525954246521,3.725260019302368,3.7252607345581055,3.7252612113952637,3.7252614498138428,3.72526216506958,3.7252631187438965,3.7252633571624756,3.725263833999634,3.725264549255371,3.7252652645111084,3.7252657413482666,3.7252659797668457,3.725266933441162,3.7252676486968994,3.7252678871154785,3.7252683639526367,3.725269079208374,3.7252700328826904,3.7252700328826904,3.7252707481384277,3.7252707481384277,3.725271463394165,3.7252721786499023,3.7252726554870605,3.7252728939056396,3.725273847579956,3.725273847579956,3.7252745628356934,3.7252748012542725,3.7252752780914307,3.725275993347168,3.725276470184326,3.7252767086029053,3.7252771854400635,3.7252771854400635,3.7252776622772217,3.725277900695801,3.725278377532959,3.725278615951538,3.7252790927886963,3.7252790927886963,3.7252795696258545,3.7252798080444336,3.7252798080444336,3.7252798080444336,3.725280284881592,3.725280523300171,3.725280523300171],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"}]}]);
                        }).then(function(){
                            
var gd = document.getElementById('7d1b0ec9-5d91-4ba4-b13c-dfc5cff3fd45');
var x = new MutationObserver(function (mutations, observer) {{
        var display = window.getComputedStyle(gd).display;
        if (!display || display === 'none') {{
            console.log([gd, 'removed!']);
            Plotly.purge(gd);
            observer.disconnect();
        }}
}});

// Listen for the removal of the full notebook cells
var notebookContainer = gd.closest('#notebook-container');
if (notebookContainer) {{
    x.observe(notebookContainer, {childList: true});
}}

// Listen for the clearing of the current output cell
var outputEl = gd.closest('.output');
if (outputEl) {{
    x.observe(outputEl, {childList: true});
}}

                        })                };                });            </script>        </div>
</div>
</div>
</section>
</section>
<section id="optimized-implementation" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="optimized-implementation">Optimized Implementation</h2>
<p>The implementation above is roughly 1.5s which is slow. Let’s perform the algorithm on multiple data points simulataneously. We’ll then move the operations onto the GPU.</p>
<section id="calculate-distances-1" class="level3">
<h3 class="anchored" data-anchor-id="calculate-distances-1">Calculate Distances</h3>
<blockquote class="blockquote">
<p>For each data point <img src="https://latex.codecogs.com/png.latex?x"> in the dataset, calculate the distance between <img src="https://latex.codecogs.com/png.latex?x"> and every other data point in the dataset.</p>
</blockquote>
<div id="59262de0" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb30" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb30-1">X <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> data.clone()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> X.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="40">
<pre><code>torch.Size([1500, 2])</code></pre>
</div>
</div>
<p>We’ll begin with a batch size of 8.</p>
<div id="1c8a3759" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb32" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb32-1">bs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span></span>
<span id="cb32-2">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> X[:bs, :]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> x</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="41">
<pre><code>tensor([[  0.611, -20.199],
        [  4.455, -24.188],
        [  2.071, -20.446],
        [  1.011, -23.082],
        [  4.516, -22.281],
        [ -0.149, -22.113],
        [  4.029, -18.819],
        [  2.960, -18.646]])</code></pre>
</div>
</div>
<div id="4a1e5fe8" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb34" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb34-1">x.shape, X.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="42">
<pre><code>(torch.Size([8, 2]), torch.Size([1500, 2]))</code></pre>
</div>
</div>
<div id="ade24b4a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb36" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb36-1">x[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, :].shape, X[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, ...].shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="43">
<pre><code>(torch.Size([8, 1, 2]), torch.Size([1, 1500, 2]))</code></pre>
</div>
</div>
<div id="c0183997" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb38" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb38-1">x[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, :] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> X[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, ...]</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="44">
<pre><code>tensor([[[  0.000,   0.000],
         [ -3.844,   3.989],
         [ -1.460,   0.247],
         ...,
         [-25.316, -26.796],
         [-17.938, -23.610],
         [-24.006, -28.684]],

        [[  3.844,  -3.989],
         [  0.000,   0.000],
         [  2.383,  -3.742],
         ...,
         [-21.472, -30.786],
         [-14.094, -27.599],
         [-20.162, -32.673]],

        [[  1.460,  -0.247],
         [ -2.383,   3.742],
         [  0.000,   0.000],
         ...,
         [-23.856, -27.043],
         [-16.477, -23.857],
         [-22.546, -28.931]],

        ...,

        [[ -0.759,  -1.914],
         [ -4.603,   2.076],
         [ -2.220,  -1.667],
         ...,
         [-26.076, -28.710],
         [-18.697, -25.523],
         [-24.766, -30.598]],

        [[  3.418,   1.380],
         [ -0.426,   5.369],
         [  1.958,   1.627],
         ...,
         [-21.898, -25.417],
         [-14.520, -22.230],
         [-20.588, -27.304]],

        [[  2.349,   1.553],
         [ -1.495,   5.542],
         [  0.889,   1.800],
         ...,
         [-22.967, -25.243],
         [-15.589, -22.057],
         [-21.657, -27.131]]])</code></pre>
</div>
</div>
<div id="3f4da544" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb40" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb40-1">(x[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, :] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> X[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, ...]).shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="45">
<pre><code>torch.Size([8, 1500, 2])</code></pre>
</div>
</div>
<div id="277af1b2" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb42" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb42-1">dists <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (x[:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, :] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> X[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, ...]).square().<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).sqrt()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> dists, dists.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="46">
<pre><code>(tensor([[ 0.000,  5.540,  1.481,  ..., 36.864, 29.651, 37.404],
         [ 5.540,  0.000,  4.437,  ..., 37.534, 30.989, 38.394],
         [ 1.481,  4.437,  0.000,  ..., 36.062, 28.994, 36.679],
         ...,
         [ 2.059,  5.050,  2.776,  ..., 38.784, 31.639, 39.364],
         [ 3.686,  5.386,  2.546,  ..., 33.549, 26.552, 34.196],
         [ 2.816,  5.740,  2.007,  ..., 34.128, 27.009, 34.715]]),
 torch.Size([8, 1500]))</code></pre>
</div>
</div>
</section>
<section id="calculate-weights-1" class="level3 page-columns page-full">
<h3 class="anchored" data-anchor-id="calculate-weights-1">Calculate Weights</h3>
<blockquote class="blockquote">
<p>Calculate weights for each point in the dataset by passing the calculated distances through the normal distribution.</p>
</blockquote>
<p>We can simplify the guassian kernel to a triangular kernel and still achieve the same results, with less computation.</p>
<div id="cc26cd96" class="cell page-columns page-full">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb44" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb44-1">plot_func(partial(gauss_kernel, mean<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, std<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.5</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display column-page">
<div>                            <div id="ce81d4e2-5707-4a30-8f3e-4d3385754f33" class="plotly-graph-div" style="height:576px; width:1024px;"></div>            <script type="text/javascript">                require(["plotly"], function(Plotly) {                    window.PLOTLYENV=window.PLOTLYENV || {};                                    if (document.getElementById("ce81d4e2-5707-4a30-8f3e-4d3385754f33")) {                    Plotly.newPlot(                        "ce81d4e2-5707-4a30-8f3e-4d3385754f33",                        [{"marker":{"color":"#d92310"},"x":[0.0,0.10101009905338287,0.20202019810676575,0.3030303120613098,0.4040403962135315,0.5050504803657532,0.6060606241226196,0.7070707082748413,0.808080792427063,0.9090908765792847,1.0101009607315063,1.111111044883728,1.2121212482452393,1.313131332397461,1.4141414165496826,1.5151515007019043,1.616161584854126,1.7171716690063477,1.8181817531585693,1.919191837310791,2.0202019214630127,2.1212120056152344,2.222222089767456,2.3232321739196777,2.4242424964904785,2.5252525806427,2.626262664794922,2.7272727489471436,2.8282828330993652,2.929292917251587,3.0303030014038086,3.1313130855560303,3.232323169708252,3.3333332538604736,3.4343433380126953,3.535353422164917,3.6363635063171387,3.7373735904693604,3.838383674621582,3.9393937587738037,4.040403842926025,4.141414165496826,4.242424011230469,4.3434343338012695,4.444444179534912,4.545454502105713,4.6464643478393555,4.747474670410156,4.848484992980957,4.9494948387146,5.0505051612854,5.151515007019043,5.252525329589844,5.3535356521606445,5.454545497894287,5.555555820465088,5.6565656661987305,5.757575988769531,5.858585834503174,5.959596157073975,6.060606002807617,6.161616325378418,6.2626261711120605,6.363636493682861,6.464646339416504,6.565656661987305,6.666666507720947,6.767676830291748,6.868687152862549,6.969696998596191,7.070707321166992,7.171717166900635,7.2727274894714355,7.373737335205078,7.474747657775879,7.5757575035095215,7.676767826080322,7.777777671813965,7.878787994384766,7.979797840118408,8.08080768585205,8.181818008422852,8.282828330993652,8.383838653564453,8.484848976135254,8.585858345031738,8.686868667602539,8.78787899017334,8.88888931274414,8.989898681640625,9.090909004211426,9.191919326782227,9.292929649353027,9.393939018249512,9.494949340820312,9.595959663391113,9.696969985961914,9.797979354858398,9.8989896774292,10.0],"y":[0.1595769077539444,0.15944671630859375,0.15905675292015076,0.15840892493724823,0.15750640630722046,0.15635357797145844,0.15495601296424866,0.15332044661045074,0.15145468711853027,0.1493675857782364,0.14706897735595703,0.144569531083107,0.14188076555728912,0.13901486992835999,0.13598470389842987,0.13280360400676727,0.1294853538274765,0.12604409456253052,0.12249413877725601,0.11885000765323639,0.11512617766857147,0.11133713275194168,0.10749714821577072,0.10362031310796738,0.09972036629915237,0.0958106592297554,0.09190409630537033,0.08801301568746567,0.08414918929338455,0.08032375574111938,0.07654716819524765,0.07282915711402893,0.06917870044708252,0.06560403108596802,0.06211260333657265,0.058711059391498566,0.055405277758836746,0.05220034345984459,0.04910058155655861,0.046109553426504135,0.043230101466178894,0.040464334189891815,0.037813760340213776,0.035279154777526855,0.03286076337099075,0.030558215454220772,0.028370661661028862,0.026296738535165787,0.024334654211997986,0.02248224802315235,0.020736966282129288,0.019095974043011665,0.017556147649884224,0.016114164143800735,0.014766494743525982,0.013509458862245083,0.01233927346765995,0.011252064257860184,0.01024391409009695,0.009310876950621605,0.008449019864201546,0.0076544322073459625,0.006923263426870108,0.006251719314604998,0.005636107642203569,0.005072826519608498,0.004558395594358444,0.0040894486010074615,0.0036627596709877253,0.0032752424012869596,0.0029239447321742773,0.0026060710661113262,0.002318964572623372,0.002060123486444354,0.0018271876033395529,0.0016179465455934405,0.0014303296338766813,0.0012624067021533847,0.0011123797157779336,0.0009785847505554557,0.000859478022903204,0.0007536362973041832,0.000659750250633806,0.0005766188842244446,0.0005031400360167027,0.00043830907088704407,0.00038120849058032036,0.0003310059546492994,0.0002869457530323416,0.0002483450516592711,0.0002145861799363047,0.00018511386588215828,0.00015942890604492277,0.00013708397455047816,0.00011767854448407888,0.00010085522080771625,8.629600051790476e-05,7.371818355750293e-05,6.287076394073665e-05,5.353209053282626e-05],"type":"scatter"}],                        {"template":{"data":{"scatter":[{"marker":{"color":"#d92310"},"type":"scatter"}]},"layout":{"height":576,"paper_bgcolor":"#fcfcfc","plot_bgcolor":"#fcfcfc","width":1024}}},                        {"responsive": true}                    ).then(function(){
                            
var gd = document.getElementById('ce81d4e2-5707-4a30-8f3e-4d3385754f33');
var x = new MutationObserver(function (mutations, observer) {{
        var display = window.getComputedStyle(gd).display;
        if (!display || display === 'none') {{
            console.log([gd, 'removed!']);
            Plotly.purge(gd);
            observer.disconnect();
        }}
}});

// Listen for the removal of the full notebook cells
var notebookContainer = gd.closest('#notebook-container');
if (notebookContainer) {{
    x.observe(notebookContainer, {childList: true});
}}

// Listen for the clearing of the current output cell
var outputEl = gd.closest('.output');
if (outputEl) {{
    x.observe(outputEl, {childList: true});
}}

                        })                };                });            </script>        </div>
</div>
</div>
<div id="1bc3f6f0" class="cell page-columns page-full">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb45" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb45-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> tri_kernel(x, bw): <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> (<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>x<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>bw).clamp_min(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span>bw</span>
<span id="cb45-2">plot_func(partial(tri_kernel, bw<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>))</span></code></pre></div></div>
<div class="cell-output cell-output-display column-page">
<div>                            <div id="06f38a15-5712-4669-9d06-3a190d6f9371" class="plotly-graph-div" style="height:576px; width:1024px;"></div>            <script type="text/javascript">                require(["plotly"], function(Plotly) {                    window.PLOTLYENV=window.PLOTLYENV || {};                                    if (document.getElementById("06f38a15-5712-4669-9d06-3a190d6f9371")) {                    Plotly.newPlot(                        "06f38a15-5712-4669-9d06-3a190d6f9371",                        [{"marker":{"color":"#d92310"},"x":[0.0,0.10101009905338287,0.20202019810676575,0.3030303120613098,0.4040403962135315,0.5050504803657532,0.6060606241226196,0.7070707082748413,0.808080792427063,0.9090908765792847,1.0101009607315063,1.111111044883728,1.2121212482452393,1.313131332397461,1.4141414165496826,1.5151515007019043,1.616161584854126,1.7171716690063477,1.8181817531585693,1.919191837310791,2.0202019214630127,2.1212120056152344,2.222222089767456,2.3232321739196777,2.4242424964904785,2.5252525806427,2.626262664794922,2.7272727489471436,2.8282828330993652,2.929292917251587,3.0303030014038086,3.1313130855560303,3.232323169708252,3.3333332538604736,3.4343433380126953,3.535353422164917,3.6363635063171387,3.7373735904693604,3.838383674621582,3.9393937587738037,4.040403842926025,4.141414165496826,4.242424011230469,4.3434343338012695,4.444444179534912,4.545454502105713,4.6464643478393555,4.747474670410156,4.848484992980957,4.9494948387146,5.0505051612854,5.151515007019043,5.252525329589844,5.3535356521606445,5.454545497894287,5.555555820465088,5.6565656661987305,5.757575988769531,5.858585834503174,5.959596157073975,6.060606002807617,6.161616325378418,6.2626261711120605,6.363636493682861,6.464646339416504,6.565656661987305,6.666666507720947,6.767676830291748,6.868687152862549,6.969696998596191,7.070707321166992,7.171717166900635,7.2727274894714355,7.373737335205078,7.474747657775879,7.5757575035095215,7.676767826080322,7.777777671813965,7.878787994384766,7.979797840118408,8.08080768585205,8.181818008422852,8.282828330993652,8.383838653564453,8.484848976135254,8.585858345031738,8.686868667602539,8.78787899017334,8.88888931274414,8.989898681640625,9.090909004211426,9.191919326782227,9.292929649353027,9.393939018249512,9.494949340820312,9.595959663391113,9.696969985961914,9.797979354858398,9.8989896774292,10.0],"y":[1.0,0.9873737096786499,0.9747474789619446,0.9621211886405945,0.9494949579238892,0.9368686676025391,0.9242424368858337,0.9116161465644836,0.8989899158477783,0.8863636255264282,0.8737373948097229,0.8611111044883728,0.8484848737716675,0.8358585834503174,0.8232322931289673,0.810606062412262,0.7979798316955566,0.7853535413742065,0.7727272510528564,0.7601010203361511,0.7474747896194458,0.7348484992980957,0.7222222089767456,0.7095959782600403,0.6969696879386902,0.6843434572219849,0.6717171669006348,0.6590908765792847,0.6464646458625793,0.633838415145874,0.6212121248245239,0.6085858345031738,0.5959596037864685,0.5833333730697632,0.5707070827484131,0.558080792427063,0.5454545617103577,0.5328283309936523,0.5202020406723022,0.5075757503509521,0.4949495196342468,0.48232322931289673,0.4696969985961914,0.4570707082748413,0.444444477558136,0.4318181872367859,0.41919195652008057,0.40656566619873047,0.39393937587738037,0.38131314516067505,0.36868685483932495,0.35606062412261963,0.34343433380126953,0.33080804347991943,0.3181818127632141,0.305555522441864,0.2929292917251587,0.2803030014038086,0.26767677068710327,0.2550504803657532,0.24242424964904785,0.22979795932769775,0.21717172861099243,0.20454543828964233,0.191919207572937,0.17929291725158691,0.1666666865348816,0.1540403962135315,0.1414141058921814,0.12878787517547607,0.11616158485412598,0.10353535413742065,0.09090906381607056,0.07828283309936523,0.06565654277801514,0.053030312061309814,0.04040402173995972,0.027777791023254395,0.015151500701904297,0.0025252699851989746,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],"type":"scatter"}],                        {"template":{"data":{"scatter":[{"marker":{"color":"#d92310"},"type":"scatter"}]},"layout":{"height":576,"paper_bgcolor":"#fcfcfc","plot_bgcolor":"#fcfcfc","width":1024}}},                        {"responsive": true}                    ).then(function(){
                            
var gd = document.getElementById('06f38a15-5712-4669-9d06-3a190d6f9371');
var x = new MutationObserver(function (mutations, observer) {{
        var display = window.getComputedStyle(gd).display;
        if (!display || display === 'none') {{
            console.log([gd, 'removed!']);
            Plotly.purge(gd);
            observer.disconnect();
        }}
}});

// Listen for the removal of the full notebook cells
var notebookContainer = gd.closest('#notebook-container');
if (notebookContainer) {{
    x.observe(notebookContainer, {childList: true});
}}

// Listen for the clearing of the current output cell
var outputEl = gd.closest('.output');
if (outputEl) {{
    x.observe(outputEl, {childList: true});
}}

                        })                };                });            </script>        </div>
</div>
</div>
<div id="40b87626" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb46" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb46-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>timeit gauss_kernel(dists, mean<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, std<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.5</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>311 µs ± 8.06 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)</code></pre>
</div>
</div>
<div id="9f177545" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb48" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb48-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>timeit tri_kernel(dists, bw<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>25 µs ± 594 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)</code></pre>
</div>
</div>
<div id="94355c04" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb50" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb50-1">gauss_kernel(dists, mean<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, std<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.5</span>), tri_kernel(dists, bw<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="55">
<pre><code>(tensor([[    0.160,     0.014,     0.134,  ...,     0.000,     0.000,     0.000],
         [    0.014,     0.160,     0.033,  ...,     0.000,     0.000,     0.000],
         [    0.134,     0.033,     0.160,  ...,     0.000,     0.000,     0.000],
         ...,
         [    0.114,     0.021,     0.086,  ...,     0.000,     0.000,     0.000],
         [    0.054,     0.016,     0.095,  ...,     0.000,     0.000,     0.000],
         [    0.085,     0.011,     0.116,  ...,     0.000,     0.000,     0.000]]),
 tensor([[1.000, 0.308, 0.815,  ..., 0.000, 0.000, 0.000],
         [0.308, 1.000, 0.445,  ..., 0.000, 0.000, 0.000],
         [0.815, 0.445, 1.000,  ..., 0.000, 0.000, 0.000],
         ...,
         [0.743, 0.369, 0.653,  ..., 0.000, 0.000, 0.000],
         [0.539, 0.327, 0.682,  ..., 0.000, 0.000, 0.000],
         [0.648, 0.282, 0.749,  ..., 0.000, 0.000, 0.000]]))</code></pre>
</div>
</div>
<div id="beab4640" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb52" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb52-1">ws <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tri_kernel(dists, bw<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> ws.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="56">
<pre><code>torch.Size([8, 1500])</code></pre>
</div>
</div>
</section>
<section id="move-the-points" class="level3 page-columns page-full">
<h3 class="anchored" data-anchor-id="move-the-points">Move the Points</h3>
<blockquote class="blockquote">
<p>Calculate the weighted average for all points in the dataset. This weighted average is the new location for <img src="https://latex.codecogs.com/png.latex?x"></p>
</blockquote>
<div id="dab9d0a5" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb54" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb54-1">ws.shape, X.shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="59">
<pre><code>(torch.Size([8, 1500]), torch.Size([1500, 2]))</code></pre>
</div>
</div>
<div id="487ed907" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb56" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb56-1">ws[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>].shape, X[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, ...].shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="60">
<pre><code>(torch.Size([8, 1500, 1]), torch.Size([1, 1500, 2]))</code></pre>
</div>
</div>
<div id="e5f46e62" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb58" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb58-1">(ws[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> X[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, ...]).shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="61">
<pre><code>torch.Size([8, 1500, 2])</code></pre>
</div>
</div>
<div id="796e5b32" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb60" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb60-1">(ws[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> X[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, ...]).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).shape</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="62">
<pre><code>torch.Size([8, 2])</code></pre>
</div>
</div>
<div id="e6eb9268" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb62" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb62-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>timeit (ws[..., <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> X[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, ...]).<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>144 µs ± 31.2 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)</code></pre>
</div>
</div>
<p>Let’s have another look at formula for weighted average.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cfrac%7B%5Csum%20wx%7D%7B%5Csum%20w%7D%0A"></p>
<p>The numerator is actually the <a href="https://en.wikipedia.org/wiki/Matrix_multiplication#Definition">definition</a> for matrix multiplication! Therefore we can speed up the operation above by using the <code>@</code> operator!</p>
<div id="2bc8d74a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb64" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb64-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>timeit ws <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> X</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>7.64 µs ± 184 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)</code></pre>
</div>
</div>
<p>A roughly 40% speed up!</p>
<div id="1da2c1d5" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb66" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb66-1">x <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (ws <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> X) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> ws.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, keepdim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> x</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="65">
<pre><code>tensor([[  2.049, -20.954],
        [  3.108, -21.923],
        [  2.441, -21.021],
        [  2.176, -21.616],
        [  3.082, -21.466],
        [  1.842, -21.393],
        [  2.946, -20.632],
        [  2.669, -20.594]])</code></pre>
</div>
</div>
<p>And there you have it! We performed this algorithm on 8 data points simultaneously!</p>
<p>Let’s encapsulate the code so we can perform it over all data points and time it.</p>
<div id="f243608b" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb68" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb68-1">?<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">slice</span></span></code></pre></div></div>
</div>
<div id="aa57a700" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb69" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb69-1">bs</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="69">
<pre><code>8</code></pre>
</div>
</div>
<div id="2e18885a" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb71" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb71-1"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1508</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1500</span>)</span></code></pre></div></div>
<div class="cell-output cell-output-display" data-execution_count="70">
<pre><code>1500</code></pre>
</div>
</div>
<div id="632218f0" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb73" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb73-1">X <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> data.clone()</span>
<span id="cb73-2">n <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(data)</span>
<span id="cb73-3">bs <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span></span>
<span id="cb73-4"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, n, bs):</span>
<span id="cb73-5">    s <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">slice</span>(i, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>bs, n))</span>
<span id="cb73-6">    dists <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (X[s][:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, :] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> X[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, ...]).square().<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).sqrt()</span>
<span id="cb73-7">    ws <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> egauss_kernel(dists, mean<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, std<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.5</span>)</span>
<span id="cb73-8">    X[s] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (ws <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> X) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> ws.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, keepdim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span></code></pre></div></div>
</div>
<div id="7154cbb9" class="cell page-columns page-full">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb74" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb74-1">plot_data(centroids<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, X, n_samples)</span></code></pre></div></div>
<div class="cell-output cell-output-display column-page">
<div>                            <div id="97c097a6-2f4e-4227-a94a-c9f7c4f3008d" class="plotly-graph-div" style="height:576px; width:1024px;"></div>            <script type="text/javascript">                require(["plotly"], function(Plotly) {                    window.PLOTLYENV=window.PLOTLYENV || {};                                    if (document.getElementById("97c097a6-2f4e-4227-a94a-c9f7c4f3008d")) {                    Plotly.newPlot(                        "97c097a6-2f4e-4227-a94a-c9f7c4f3008d",                        [{"marker":{"color":"#636EFA","size":3},"mode":"markers","name":"cluster 0","x":[1.6946266889572144,3.451626777648926,2.3653011322021484,1.9348987340927124,3.4310247898101807,1.3723405599594116,3.208442449569702,2.745055675506592,0.9619067907333374,4.267347812652588,2.712491512298584,3.5134286880493164,2.3592238426208496,0.711961030960083,0.4545886814594269,1.2533621788024902,2.46651291847229,2.726290225982666,3.398402214050293,1.807930827140808,1.1576652526855469,3.997157573699951,2.3161654472351074,2.979919195175171,2.3996262550354004,2.5476620197296143,-0.5049120187759399,2.2316343784332275,3.909813642501831,2.2144768238067627,3.5135927200317383,2.1956167221069336,2.645399570465088,2.0542514324188232,1.4631602764129639,2.0585474967956543,1.6915644407272339,2.9296178817749023,1.840678334236145,1.5837104320526123,0.49679118394851685,3.0052943229675293,2.486318349838257,4.015147686004639,2.2219126224517822,3.184940814971924,1.8370676040649414,2.997020721435547,2.077298879623413,3.4158554077148438,2.6481354236602783,2.1985373497009277,2.8942413330078125,1.4283627271652222,2.944667339324951,2.964273691177368,1.6419023275375366,3.015951633453369,2.101039171218872,3.0330288410186768,1.8511332273483276,1.5410199165344238,2.191232442855835,2.7713944911956787,2.9626572132110596,2.981961965560913,2.4161033630371094,0.7570104598999023,3.728142023086548,2.295381546020508,2.7129533290863037,1.805544376373291,2.7366979122161865,3.411176919937134,4.114264965057373,3.1157727241516113,2.612553596496582,2.255019187927246,3.0966567993164062,2.166029214859009,3.0312581062316895,2.4992072582244873,3.5044848918914795,2.6775009632110596,2.0910696983337402,2.0600528717041016,2.020047903060913,3.199538230895996,2.2585487365722656,3.0867629051208496,3.0099833011627197,2.8049447536468506,2.7721519470214844,3.5652761459350586,0.8395788073539734,1.869541049003601,2.325021266937256,1.713260531425476,3.346999406814575,1.5696803331375122,0.4958135485649109,3.033019781112671,3.0360023975372314,2.5957751274108887,2.9073972702026367,2.018690347671509,2.010044813156128,2.7933475971221924,1.8182603120803833,2.199535846710205,2.3915438652038574,3.4418344497680664,2.826584577560425,3.2941854000091553,2.5443432331085205,2.7648725509643555,1.762680172920227,2.514033079147339,2.30035138130188,2.4046154022216797,2.115978717803955,2.31915283203125,2.1334116458892822,2.9470396041870117,2.8719539642333984,2.3212392330169678,2.9645707607269287,2.597245693206787,2.5753049850463867,2.204564332962036,3.571776866912842,2.92714262008667,1.7349555492401123,2.3975000381469727,2.6328301429748535,2.929521322250366,2.5118610858917236,2.6439404487609863,2.8348660469055176,3.8042123317718506,2.0274240970611572,2.7153525352478027,2.7436439990997314,2.94663143157959,2.3288636207580566,2.481165885925293,2.7516140937805176,2.207282543182373,3.489365816116333,3.073941707611084,2.455613136291504,3.1769280433654785,2.809131145477295,2.702218532562256,2.971710443496704,3.0460152626037598,2.822737216949463,2.1428139209747314,2.800595283508301,1.719226360321045,1.7262073755264282,2.5150461196899414,2.832249641418457,2.1802170276641846,2.61110782623291,1.8339409828186035,2.6364753246307373,2.770414352416992,2.642167568206787,2.6506683826446533,3.281550884246826,2.461663246154785,2.668562412261963,2.0344579219818115,3.8460731506347656,3.6134705543518066,2.895617961883545,2.5763843059539795,2.401663303375244,2.9332096576690674,2.443126916885376,2.612816095352173,2.0624876022338867,2.5733418464660645,2.656236410140991,3.312218427658081,2.024514675140381,1.8777104616165161,2.786665201187134,2.499788999557495,3.2595648765563965,2.1729648113250732,2.688157558441162,2.9209301471710205,2.005692481994629,2.144188642501831,3.108494281768799,2.3627641201019287,2.8836376667022705,2.5795493125915527,2.1638662815093994,2.1248838901519775,3.8615407943725586,2.4994075298309326,2.5284295082092285,2.15313458442688,2.9123291969299316,2.769214391708374,2.535602569580078,3.069316864013672,2.7003865242004395,2.906301498413086,2.4789512157440186,2.495800256729126,2.692580223083496,2.824392557144165,2.5734143257141113,3.269033670425415,1.9835753440856934,2.4009721279144287,2.0370373725891113,2.887155294418335,2.2978365421295166,2.528406858444214,2.4633429050445557,2.7234842777252197,2.8516767024993896,3.1619441509246826,2.7116830348968506,2.6994681358337402,2.9946680068969727,2.4468491077423096,2.615464210510254,2.426917791366577,2.918769598007202,2.638561248779297,2.589190721511841,2.6593494415283203,2.5259695053100586,2.8316049575805664,2.0764966011047363,2.1248834133148193,2.6592400074005127,2.7588863372802734,2.6326723098754883,2.9049055576324463,2.567277669906616,2.3772075176239014,2.2731831073760986,2.235405445098877],"y":[-20.786109924316406,-22.400897979736328,-20.909433364868164,-21.912155151367188,-21.675926208496094,-21.517879486083984,-20.255956649780273,-20.188335418701172,-21.38019371032715,-21.513225555419922,-20.50708770751953,-21.822294235229492,-21.343727111816406,-21.395282745361328,-20.51968002319336,-22.28143882751465,-21.191001892089844,-19.07025146484375,-21.75218391418457,-21.619733810424805,-20.01335906982422,-22.11908531188965,-21.364259719848633,-20.977096557617188,-21.362314224243164,-21.467493057250977,-22.062273025512695,-20.405458450317383,-21.18134117126465,-22.88274383544922,-21.50473403930664,-20.55072784423828,-21.041072845458984,-20.53849220275879,-22.482128143310547,-21.615455627441406,-20.201900482177734,-21.300277709960938,-21.43254280090332,-20.67633628845215,-20.79852294921875,-20.958345413208008,-21.875396728515625,-20.31330680847168,-21.29486083984375,-20.401107788085938,-21.033935546875,-20.04222297668457,-20.573026657104492,-22.04601287841797,-21.203275680541992,-20.795257568359375,-19.65696907043457,-19.78553009033203,-21.31409454345703,-22.033559799194336,-21.357370376586914,-21.132495880126953,-21.489761352539062,-20.7674503326416,-20.373119354248047,-20.80778694152832,-20.76485824584961,-20.356569290161133,-21.12126922607422,-21.699100494384766,-21.70237159729004,-21.666635513305664,-22.376258850097656,-20.84409523010254,-22.226213455200195,-20.34130859375,-21.293970108032227,-21.97161293029785,-21.594696044921875,-21.15825843811035,-21.531269073486328,-21.15963363647461,-21.906373977661133,-21.11066436767578,-21.831192016601562,-21.111928939819336,-21.456378936767578,-21.618040084838867,-21.600160598754883,-21.0513916015625,-21.25149917602539,-21.09637451171875,-21.664958953857422,-21.058786392211914,-21.595064163208008,-20.25519561767578,-20.740007400512695,-21.67999839782715,-22.00813865661621,-21.173660278320312,-21.089887619018555,-20.66398811340332,-21.687578201293945,-21.301067352294922,-21.104246139526367,-20.803119659423828,-20.85480499267578,-21.245101928710938,-21.69455909729004,-21.643918991088867,-23.503055572509766,-21.7784423828125,-22.319063186645508,-20.56761932373047,-21.554561614990234,-21.194612503051758,-20.861976623535156,-21.335357666015625,-21.4759521484375,-21.445531845092773,-21.25752830505371,-21.613441467285156,-21.031051635742188,-20.51285743713379,-20.77911376953125,-21.410934448242188,-20.03436279296875,-21.157100677490234,-21.318317413330078,-21.150556564331055,-21.59787940979004,-21.335214614868164,-21.93220329284668,-20.99569320678711,-18.867403030395508,-21.263832092285156,-21.663320541381836,-20.849445343017578,-21.577566146850586,-21.12071990966797,-20.51508331298828,-21.48161506652832,-21.519336700439453,-19.901302337646484,-21.581403732299805,-21.178733825683594,-21.179086685180664,-21.071582794189453,-20.87057876586914,-21.028263092041016,-21.626434326171875,-20.56739616394043,-21.174135208129883,-21.562767028808594,-21.313579559326172,-22.002511978149414,-21.42713165283203,-21.011850357055664,-20.990880966186523,-21.094520568847656,-21.34895896911621,-21.204145431518555,-21.25323486328125,-21.097305297851562,-21.064313888549805,-21.178829193115234,-20.91888999938965,-21.444984436035156,-20.850465774536133,-21.292871475219727,-21.12318992614746,-21.50851058959961,-21.5496883392334,-21.183456420898438,-20.370710372924805,-21.426626205444336,-21.318058013916016,-21.34569549560547,-21.88331413269043,-20.807987213134766,-21.846492767333984,-21.37298011779785,-21.728607177734375,-20.94284439086914,-21.232736587524414,-21.172346115112305,-20.76527214050293,-21.862712860107422,-20.998594284057617,-20.705636978149414,-21.211639404296875,-21.139495849609375,-21.18589210510254,-21.484546661376953,-20.6724853515625,-21.45094108581543,-21.157106399536133,-21.77313232421875,-21.294668197631836,-21.085678100585938,-20.492996215820312,-21.09013557434082,-20.55448341369629,-21.25468635559082,-21.10371208190918,-21.105737686157227,-17.540170669555664,-20.851951599121094,-21.609668731689453,-21.10993194580078,-21.722637176513672,-21.028026580810547,-21.15576171875,-20.725677490234375,-20.921703338623047,-20.938663482666016,-21.086891174316406,-21.220592498779297,-21.20673370361328,-20.783832550048828,-21.273273468017578,-21.023162841796875,-20.88538932800293,-20.986465454101562,-20.778488159179688,-20.89864158630371,-21.190723419189453,-21.05451202392578,-21.506433486938477,-20.98109245300293,-20.845823287963867,-21.764638900756836,-21.32682228088379,-21.19165802001953,-21.235593795776367,-21.518861770629883,-21.288541793823242,-21.20479393005371,-21.362184524536133,-21.23247718811035,-21.32361602783203,-21.417612075805664,-21.408344268798828,-21.1187686920166,-20.90416145324707,-21.111066818237305,-21.11927604675293,-21.037874221801758,-21.099611282348633,-21.08454704284668,-21.13610076904297,-21.103343963623047,-20.96019172668457,-21.458873748779297],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"#EF553B","size":3},"mode":"markers","name":"cluster 1","x":[10.553921699523926,10.373069763183594,11.677619934082031,9.75402545928955,11.223529815673828,10.842337608337402,10.936230659484863,10.845635414123535,11.160155296325684,11.179275512695312,11.085128784179688,12.736167907714844,12.036944389343262,12.90036678314209,9.844823837280273,10.154984474182129,11.268963813781738,12.772796630859375,10.357660293579102,11.737223625183105,12.793660163879395,12.943015098571777,11.032095909118652,11.527918815612793,11.155333518981934,11.363434791564941,10.894728660583496,11.910030364990234,12.683411598205566,11.275266647338867,10.382612228393555,12.259005546569824,11.319459915161133,10.641239166259766,11.776023864746094,10.968470573425293,10.554255485534668,11.525429725646973,11.821685791015625,11.294366836547852,8.058490753173828,11.292505264282227,11.144932746887207,10.954424858093262,11.917519569396973,10.363914489746094,11.578357696533203,10.510771751403809,15.91190242767334,10.627205848693848,9.692631721496582,11.095588684082031,12.036667823791504,10.61976146697998,11.258709907531738,11.14928913116455,10.771896362304688,11.15629768371582,11.730637550354004,11.765854835510254,12.370894432067871,11.28772258758545,10.527587890625,11.634882926940918,9.526544570922852,10.983451843261719,10.786776542663574,11.20235538482666,11.004183769226074,12.174455642700195,11.288979530334473,11.023300170898438,10.786253929138184,10.934151649475098,11.068869590759277,11.055761337280273,12.047718048095703,10.589033126831055,15.355889320373535,11.078619956970215,10.872176170349121,10.059722900390625,12.095918655395508,10.996366500854492,11.783126831054688,10.12055492401123,12.3421630859375,10.256416320800781,9.177756309509277,11.16922378540039,11.446324348449707,12.061436653137207,9.82693862915039,12.384444236755371,12.51307201385498,10.860472679138184,11.184861183166504,10.968304634094238,11.286765098571777,12.437787055969238,10.826624870300293,12.189024925231934,11.486734390258789,10.373849868774414,10.308329582214355,10.565869331359863,11.09671401977539,11.102288246154785,12.212904930114746,9.325033187866211,11.113492965698242,11.954331398010254,11.129271507263184,10.132048606872559,11.345004081726074,11.116432189941406,10.592974662780762,10.183323860168457,11.426695823669434,10.874956130981445,9.82644271850586,11.143717765808105,10.295689582824707,11.045184135437012,10.768241882324219,11.440184593200684,9.23656177520752,11.223176002502441,11.054121017456055,11.538626670837402,10.481975555419922,10.89372730255127,11.544700622558594,11.213761329650879,11.043502807617188,11.354451179504395,11.525505065917969,11.359153747558594,10.356878280639648,12.580635070800781,10.898523330688477,11.541097640991211,10.560519218444824,11.217844009399414,10.999299049377441,10.662837028503418,10.777998924255371,10.208235740661621,11.04532527923584,10.969571113586426,11.300439834594727,11.417377471923828,12.09776782989502,11.073554992675781,11.318260192871094,11.040632247924805,11.029877662658691,11.70118522644043,10.761783599853516,9.678243637084961,11.041146278381348,10.645988464355469,11.481039047241211,12.20847225189209,11.326652526855469,10.749006271362305,11.447647094726562,10.867829322814941,10.688591957092285,10.525483131408691,11.463300704956055,11.065678596496582,11.423497200012207,10.960894584655762,10.872761726379395,11.249581336975098,10.711943626403809,11.198227882385254,10.586920738220215,11.101282119750977,10.40683650970459,11.715349197387695,11.149430274963379,11.33705997467041,10.829581260681152,11.310302734375,10.856027603149414,10.881921768188477,11.23937702178955,11.063117027282715,10.6342134475708,11.230323791503906,10.232300758361816,10.741154670715332,11.152819633483887,10.993390083312988,10.039007186889648,11.124027252197266,11.355137825012207,11.30525016784668,11.068922996520996,11.321916580200195,11.208259582519531,11.721229553222656,11.190749168395996,10.58654499053955,11.073712348937988,6.664103031158447,11.200885772705078,11.827878952026367,10.472994804382324,11.014266967773438,11.096818923950195,10.70541000366211,11.16626262664795,10.9259033203125,11.765626907348633,11.337611198425293,11.484273910522461,11.301698684692383,11.019732475280762,10.931825637817383,9.42722225189209,10.858692169189453,11.002876281738281,9.662773132324219,10.804474830627441,10.334888458251953,11.246848106384277,11.349164962768555,9.073573112487793,11.447039604187012,10.660975456237793,10.803458213806152,11.148321151733398,11.009312629699707,11.031085968017578,12.19286823272705,11.162300109863281,9.754342079162598,10.935678482055664,11.375327110290527,11.059879302978516,11.226101875305176,11.095330238342285,11.004302024841309,11.127501487731934,7.742171287536621,11.018129348754883,11.037155151367188],"y":[10.839705467224121,10.18629264831543,12.09248161315918,11.568831443786621,10.497702598571777,11.271977424621582,9.269186973571777,10.026692390441895,11.437603950500488,12.637978553771973,10.86895751953125,12.048407554626465,11.090347290039062,10.437949180603027,11.344112396240234,10.431021690368652,10.487024307250977,11.344334602355957,12.204328536987305,9.550714492797852,9.798099517822266,11.722485542297363,9.959817886352539,12.364190101623535,11.22994613647461,10.893816947937012,10.52434253692627,10.624955177307129,9.862893104553223,9.795900344848633,9.701075553894043,10.039278030395508,9.79199504852295,11.443364143371582,10.387687683105469,10.560111045837402,11.942910194396973,12.133355140686035,11.048905372619629,10.144702911376953,10.428884506225586,11.780381202697754,11.692931175231934,9.281023979187012,10.776604652404785,12.03515338897705,10.311727523803711,11.393058776855469,11.5847806930542,11.664133071899414,11.496661186218262,11.20753002166748,8.8077974319458,11.340070724487305,10.857340812683105,11.510774612426758,11.338852882385254,10.273219108581543,10.65641975402832,8.497647285461426,10.624629020690918,12.281881332397461,9.497895240783691,11.588401794433594,11.292281150817871,11.339044570922852,11.553509712219238,11.1256742477417,11.03908634185791,9.365856170654297,11.98643684387207,10.915253639221191,11.144596099853516,10.591938018798828,10.176939964294434,9.85556411743164,11.308160781860352,9.976273536682129,9.99977970123291,10.67661190032959,10.541159629821777,9.267237663269043,12.045924186706543,11.609452247619629,11.237030982971191,10.528504371643066,12.32811450958252,10.305167198181152,9.459239959716797,11.621749877929688,10.226873397827148,10.364579200744629,11.279064178466797,11.848688125610352,10.562063217163086,11.96163558959961,10.656432151794434,12.077720642089844,11.467361450195312,10.64436149597168,10.886960983276367,10.695453643798828,10.705008506774902,10.679256439208984,10.525821685791016,10.000770568847656,11.438687324523926,9.672282218933105,9.885039329528809,10.659366607666016,10.82849407196045,10.223207473754883,11.460036277770996,11.881269454956055,11.769515037536621,12.565447807312012,10.225393295288086,10.942964553833008,11.101203918457031,10.781396865844727,10.964802742004395,11.291158676147461,10.924199104309082,10.966529846191406,11.410964965820312,10.921091079711914,11.06544303894043,9.902402877807617,11.78459358215332,11.386634826660156,11.393950462341309,10.359864234924316,8.690319061279297,9.864398002624512,11.950210571289062,11.043943405151367,10.629143714904785,11.201871871948242,11.22220230102539,10.052284240722656,10.521278381347656,10.249852180480957,10.255687713623047,10.963577270507812,10.615777015686035,11.223052024841309,11.329751968383789,10.171187400817871,10.467543601989746,10.910808563232422,9.827180862426758,10.475188255310059,10.728328704833984,11.744560241699219,11.185853958129883,10.558919906616211,11.842432022094727,10.054574012756348,11.298364639282227,10.837153434753418,10.842443466186523,10.778003692626953,10.456625938415527,11.848006248474121,10.452713012695312,10.910658836364746,10.392743110656738,11.282575607299805,11.176374435424805,9.905013084411621,10.658744812011719,10.748847961425781,10.09991455078125,10.677647590637207,10.693370819091797,11.093989372253418,11.226278305053711,11.538838386535645,10.864468574523926,10.804872512817383,10.9542875289917,10.74661636352539,10.6780424118042,10.932697296142578,11.498106956481934,11.10471248626709,10.963251113891602,10.590431213378906,10.930891990661621,11.0252103805542,10.42723274230957,11.182792663574219,11.601231575012207,10.886148452758789,10.630379676818848,11.415539741516113,10.257537841796875,10.569375991821289,11.632540702819824,10.909303665161133,11.348992347717285,10.861268043518066,10.4345121383667,10.590957641601562,11.063261985778809,10.574975967407227,10.441756248474121,17.166465759277344,11.16532039642334,11.010457038879395,10.85804271697998,10.802297592163086,10.714029312133789,10.865208625793457,10.65395736694336,11.103914260864258,10.69882869720459,10.554534912109375,10.057065963745117,10.731228828430176,10.607447624206543,11.231781005859375,10.859301567077637,10.796797752380371,10.70654010772705,11.063481330871582,10.854194641113281,11.315988540649414,11.154101371765137,10.967211723327637,9.328433990478516,10.729284286499023,11.255678176879883,10.946922302246094,10.770726203918457,10.984095573425293,9.444052696228027,10.332416534423828,10.791669845581055,10.992944717407227,10.99553108215332,10.30049991607666,10.958738327026367,10.883827209472656,10.773168563842773,10.72610855102539,10.936687469482422,10.833057403564453,10.838723182678223,10.46458625793457],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"#00CC96","size":3},"mode":"markers","name":"cluster 2","x":[-21.093048095703125,-18.887149810791016,-19.406997680664062,-17.715103149414062,-17.60808563232422,-19.198963165283203,-18.728525161743164,-16.552505493164062,-18.298553466796875,-19.178054809570312,-18.531465530395508,-17.91971206665039,-18.133508682250977,-19.555173873901367,-17.99525260925293,-18.76314353942871,-18.75102996826172,-17.26375389099121,-17.40165138244629,-17.727760314941406,-18.44153594970703,-18.77003288269043,-19.320598602294922,-19.96240997314453,-18.561626434326172,-18.568891525268555,-18.344825744628906,-16.824172973632812,-20.676559448242188,-19.372819900512695,-17.736528396606445,-18.286808013916016,-18.762563705444336,-20.775291442871094,-18.107912063598633,-18.787935256958008,-18.1416072845459,-17.36734390258789,-17.566064834594727,-19.162506103515625,-19.63397216796875,-17.689979553222656,-17.468303680419922,-18.57282257080078,-17.69161033630371,-17.723674774169922,-18.785844802856445,-18.184988021850586,-19.199872970581055,-19.302093505859375,-18.48624038696289,-18.572219848632812,-17.951143264770508,-17.661874771118164,-19.675230026245117,-19.583393096923828,-18.883752822875977,-19.610191345214844,-18.448148727416992,-19.937246322631836,-20.556381225585938,-18.992061614990234,-19.81107521057129,-19.631549835205078,-19.41221809387207,-18.99567985534668,-18.488176345825195,-16.69012451171875,-17.809934616088867,-19.057579040527344,-19.058481216430664,-17.956527709960938,-19.04789924621582,-19.219297409057617,-18.68551254272461,-20.354488372802734,-21.989669799804688,-18.278772354125977,-19.15352439880371,-18.635229110717773,-16.84161376953125,-20.97185516357422,-18.358983993530273,-17.91529655456543,-19.58229637145996,-19.530559539794922,-18.2714786529541,-18.976072311401367,-18.007591247558594,-18.073715209960938,-19.111305236816406,-17.618371963500977,-18.929780960083008,-21.460277557373047,-19.821741104125977,-18.837371826171875,-17.88388442993164,-18.8518009185791,-18.131450653076172,-19.72120475769043,-18.513940811157227,-19.173851013183594,-18.537891387939453,-19.700176239013672,-18.832565307617188,-18.75481605529785,-17.599567413330078,-17.175445556640625,-18.929851531982422,-17.684383392333984,-18.76637840270996,-18.204530715942383,-21.159828186035156,-18.45362663269043,-17.610549926757812,-18.672189712524414,-18.625173568725586,-19.01613998413086,-18.114273071289062,-19.400054931640625,-19.23133087158203,-18.12173843383789,-18.602449417114258,-18.998510360717773,-18.322141647338867,-18.132877349853516,-19.679040908813477,-20.607500076293945,-19.27792739868164,-18.127426147460938,-18.121797561645508,-18.13090705871582,-18.78255271911621,-20.009334564208984,-18.839439392089844,-18.658170700073242,-18.569448471069336,-18.83826446533203,-17.39067840576172,-18.861173629760742,-18.915050506591797,-18.719680786132812,-18.963441848754883,-19.445852279663086,-18.368106842041016,-18.294206619262695,-18.81901741027832,-18.256019592285156,-18.581233978271484,-19.19782829284668,-18.240646362304688,-18.90575408935547,-18.689472198486328,-18.260671615600586,-18.645401000976562,-18.63776206970215,-18.721513748168945,-19.428905487060547,-18.659460067749023,-17.852508544921875,-18.113079071044922,-18.846519470214844,-19.13294792175293,-19.85503578186035,-19.473237991333008,-19.637502670288086,-18.542776107788086,-18.529888153076172,-18.807498931884766,-18.997243881225586,-19.466007232666016,-18.691497802734375,-18.191020965576172,-18.35637092590332,-19.39901351928711,-18.619821548461914,-18.60089683532715,-18.737939834594727,-18.494752883911133,-18.969457626342773,-18.74869728088379,-18.808467864990234,-18.981014251708984,-18.860130310058594,-18.87490463256836,-19.68804168701172,-18.878215789794922,-18.88274383544922,-18.564838409423828,-17.843759536743164,-18.361495971679688,-18.69120216369629,-18.826705932617188,-18.91507339477539,-18.605552673339844,-18.425636291503906,-18.79353904724121,-18.44377899169922,-18.523962020874023,-19.0307559967041,-19.021106719970703,-18.86870574951172,-18.873075485229492,-19.01778221130371,-18.533557891845703,-18.87209129333496,-19.05012321472168,-17.798690795898438,-17.973987579345703,-19.234514236450195,-18.14335060119629,-17.886398315429688,-18.596174240112305,-18.67447853088379,-18.177749633789062,-18.944072723388672,-18.880640029907227,-18.74137306213379,-18.798091888427734,-18.71272087097168,-18.92228126525879,-18.797988891601562,-19.137739181518555,-18.83582305908203,-18.652685165405273,-18.409347534179688,-19.170387268066406,-18.747169494628906,-18.841108322143555,-18.48809242248535,-18.384925842285156,-18.39752960205078,-19.16777992248535,-18.345067977905273,-18.66018295288086,-18.934749603271484,-18.540693283081055,-18.021448135375977,-18.611122131347656,-18.68062973022461,-18.51413345336914,-18.459392547607422,-18.616819381713867,-18.841032028198242,-18.81556510925293,-18.613582611083984,-18.786670684814453,-18.8305606842041,-18.71814727783203,-18.609935760498047],"y":[-3.9462170600891113,-5.369531631469727,-4.6962890625,-5.408623695373535,-6.667224407196045,-4.902647495269775,-4.973326206207275,-5.3967156410217285,-7.863418102264404,-4.949368000030518,-5.766419410705566,-6.623761177062988,-6.72001838684082,-5.843117713928223,-5.1968793869018555,-5.024683475494385,-6.229925155639648,-4.687953948974609,-5.885583400726318,-6.241818904876709,-5.274468421936035,-6.0185770988464355,-5.175447463989258,-5.248398303985596,-5.390834808349609,-5.917530536651611,-6.165467739105225,-6.158018589019775,-4.406484127044678,-5.400921821594238,-5.579596042633057,-5.254071235656738,-5.308645248413086,-4.072803974151611,-6.763665676116943,-5.3935651779174805,-5.195196628570557,-6.66331148147583,-6.382404327392578,-4.740189075469971,-4.516123294830322,-5.154362678527832,-6.033886909484863,-7.216915130615234,-5.588120937347412,-2.4405877590179443,-5.4956207275390625,-5.8999552726745605,-5.175098896026611,-6.441885948181152,-5.78046989440918,-4.736724853515625,-5.614765167236328,-4.410458564758301,-5.4466681480407715,-4.241634368896484,-5.848226070404053,-6.021847724914551,-4.906838893890381,-4.448287010192871,-4.670368194580078,-4.170608043670654,-5.76917028427124,-5.635137557983398,-5.0940985679626465,-6.267455577850342,-5.858415603637695,-4.752541542053223,-5.306870937347412,-5.464418888092041,-4.2036213874816895,-5.6297430992126465,-4.992593765258789,-5.127712249755859,-5.551028251647949,-5.503383159637451,-4.986486911773682,-6.139240741729736,-5.275160789489746,-6.772832870483398,-7.794990539550781,-7.574618339538574,-3.6151225566864014,-4.678816795349121,-4.6346821784973145,-4.959465503692627,-3.85044264793396,-5.5266265869140625,-5.129685878753662,-6.192991256713867,-5.527575969696045,-5.301693439483643,-5.700763702392578,-6.054080009460449,-5.569858074188232,-6.282738208770752,-6.576365947723389,-4.068912506103516,-6.819095134735107,-5.510540962219238,-5.38754940032959,-6.267722129821777,-4.080472946166992,-5.048652172088623,-6.206478118896484,-5.602786540985107,-5.880502700805664,-4.8137311935424805,-4.928017616271973,-6.239509582519531,-6.1868577003479,-6.258682727813721,-4.2390313148498535,-6.003727912902832,-6.435088634490967,-4.655085563659668,-5.288344383239746,-5.211790084838867,-6.163978099822998,-5.035799980163574,-5.257792949676514,-4.733267307281494,-4.940170764923096,-5.3805952072143555,-5.334940433502197,-5.852725505828857,-5.654168128967285,-5.0661749839782715,-5.270211696624756,-4.843738555908203,-5.713778018951416,-5.782386779785156,-5.606998920440674,-5.116738796234131,-6.301544189453125,-5.3593339920043945,-4.933854103088379,-5.969257354736328,-4.691956043243408,-5.227170944213867,-5.852723121643066,-5.52439022064209,-5.401701927185059,-5.030302047729492,-5.577700138092041,-4.647595405578613,-6.113066673278809,-5.33100700378418,-5.465376377105713,-6.427457809448242,-5.982173442840576,-5.323575019836426,-5.436002731323242,-5.600407600402832,-5.297695159912109,-4.6533613204956055,-5.473896503448486,-5.169983863830566,-4.724050521850586,-5.123828887939453,-5.710773944854736,-5.715723514556885,-4.357414722442627,-6.4026031494140625,-3.96014666557312,-4.387092113494873,-5.575368404388428,-5.597004413604736,-5.213526725769043,-4.863188743591309,-5.487124919891357,-5.824517726898193,-6.080232620239258,-6.313060283660889,-5.108315944671631,-5.73466682434082,-5.083730220794678,-5.60839319229126,-6.093675136566162,-3.6923537254333496,-5.337417125701904,-5.469754219055176,-5.025766849517822,-6.1849589347839355,-5.437831401824951,-4.101319313049316,-6.109947204589844,-6.163685321807861,-5.680917739868164,-4.824565887451172,-5.152396202087402,-6.016811370849609,-5.491506576538086,-5.53620719909668,-6.529930114746094,-6.670257568359375,-5.671153545379639,-5.967051982879639,-5.619402885437012,-5.18323278427124,-5.705265045166016,-5.597776412963867,-5.033862113952637,-5.448002815246582,-5.736205577850342,-5.394132614135742,-5.411746501922607,-5.005280017852783,-6.88227653503418,-5.355778694152832,-6.419702053070068,-5.923592567443848,-5.822847843170166,-5.375254154205322,-5.309165954589844,-5.759596824645996,-5.677914619445801,-5.842088222503662,-5.378302097320557,-5.458364009857178,-5.7125043869018555,-5.20235013961792,-5.220361232757568,-5.296230792999268,-5.509459495544434,-5.645040512084961,-5.312433242797852,-5.771493434906006,-5.52752685546875,-5.393679618835449,-5.915333271026611,-5.761152267456055,-4.84112024307251,-5.453485488891602,-5.55157995223999,-5.363927841186523,-5.268054485321045,-5.168338775634766,-5.483264446258545,-4.928983688354492,-5.522541522979736,-5.733537197113037,-5.676410675048828,-5.490575790405273,-5.3100504875183105,-5.569531440734863,-5.4892988204956055,-5.350455284118652,-5.738470554351807,-5.414727687835693],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"#AB63FA","size":3},"mode":"markers","name":"cluster 3","x":[-19.73105812072754,-22.38623046875,-19.789833068847656,-19.673261642456055,-19.7297420501709,-19.65678596496582,-20.34926414489746,-21.182937622070312,-20.587705612182617,-19.80198860168457,-20.53502655029297,-21.046098709106445,-21.088794708251953,-20.561683654785156,-19.86089515686035,-20.091428756713867,-20.920331954956055,-19.6539249420166,-19.188899993896484,-20.69249725341797,-19.968225479125977,-21.067718505859375,-22.1076602935791,-22.009248733520508,-21.055757522583008,-19.974451065063477,-19.959964752197266,-21.75603675842285,-21.28110122680664,-21.64285659790039,-18.791746139526367,-20.06556510925293,-21.02452850341797,-21.649368286132812,-20.08447265625,-21.010988235473633,-21.05537223815918,-21.407333374023438,-18.839881896972656,-21.873868942260742,-21.247793197631836,-21.214563369750977,-21.196571350097656,-20.8896541595459,-20.058883666992188,-20.224227905273438,-20.463476181030273,-20.19508934020996,-19.793659210205078,-20.483495712280273,-20.299148559570312,-21.451486587524414,-19.480239868164062,-20.970300674438477,-21.835792541503906,-20.531579971313477,-20.819425582885742,-21.639448165893555,-21.116924285888672,-19.971437454223633,-20.971633911132812,-20.745716094970703,-22.11334800720215,-21.103845596313477,-21.257312774658203,-20.48525619506836,-20.321348190307617,-21.473995208740234,-21.433353424072266,-21.080333709716797,-19.562015533447266,-20.836509704589844,-19.180110931396484,-20.406814575195312,-21.323204040527344,-20.43719482421875,-22.01849365234375,-20.21715545654297,-20.744050979614258,-20.48009490966797,-20.61729621887207,-20.697940826416016,-19.800355911254883,-20.236846923828125,-20.193803787231445,-19.732345581054688,-21.17205047607422,-22.08122444152832,-22.503297805786133,-21.382081985473633,-19.47644805908203,-20.071664810180664,-21.177404403686523,-20.402881622314453,-20.604398727416992,-20.529552459716797,-20.766223907470703,-21.3272705078125,-21.127124786376953,-21.46630096435547,-20.777807235717773,-20.85765266418457,-19.838701248168945,-19.900487899780273,-20.823850631713867,-19.919326782226562,-20.245559692382812,-21.185665130615234,-20.61151885986328,-20.59654998779297,-20.75006866455078,-18.7675724029541,-20.49586296081543,-21.132598876953125,-20.625812530517578,-20.719629287719727,-21.41245460510254,-20.74220848083496,-20.362506866455078,-20.834259033203125,-20.47740364074707,-20.392017364501953,-20.12049674987793,-19.78467559814453,-21.0401611328125,-20.444828033447266,-19.976646423339844,-20.975536346435547,-21.098173141479492,-19.996843338012695,-20.302566528320312,-20.32534408569336,-21.2651424407959,-20.318416595458984,-21.656494140625,-20.28925895690918,-21.329639434814453,-20.627952575683594,-20.422863006591797,-20.569372177124023,-20.759883880615234,-20.996553421020508,-20.224401473999023,-20.559741973876953,-19.964895248413086,-19.375675201416016,-20.410552978515625,-20.60592269897461,-20.957508087158203,-20.384157180786133,-19.005857467651367,-20.504514694213867,-20.311988830566406,-21.171466827392578,-20.775928497314453,-19.7906551361084,-21.01797866821289,-20.715503692626953,-20.47544288635254,-20.48671531677246,-20.104036331176758,-21.245113372802734,-20.78017234802246,-20.728790283203125,-19.800718307495117,-19.9455509185791,-20.759864807128906,-20.544740676879883,-20.633655548095703,-20.403095245361328,-19.92422866821289,-19.82339859008789,-20.59638023376465,-20.578327178955078,-20.67357063293457,-20.39194679260254,-20.25176429748535,-20.10172462463379,-21.39612579345703,-20.598133087158203,-20.332788467407227,-20.44989585876465,-20.375354766845703,-20.74732208251953,-20.71107292175293,-20.685260772705078,-20.829301834106445,-20.72821044921875,-20.677749633789062,-20.718957901000977,-20.725276947021484,-20.555437088012695,-20.204225540161133,-20.361656188964844,-20.341598510742188,-20.62507438659668,-20.88339614868164,-19.811376571655273,-20.840181350708008,-20.37874412536621,-20.55042839050293,-20.296493530273438,-20.692394256591797,-20.715681076049805,-20.692501068115234,-20.685941696166992,-20.51426124572754,-20.52827262878418,-20.643983840942383,-20.494543075561523,-20.577966690063477,-20.746450424194336,-20.56389808654785,-20.43198585510254,-20.701467514038086,-20.840129852294922,-20.781625747680664,-20.64655113220215,-20.524513244628906,-20.592687606811523,-20.2652530670166,-20.49325180053711,-20.683704376220703,-21.4796142578125,-20.630386352539062,-20.740615844726562,-20.66598892211914,-20.727977752685547,-20.817638397216797,-20.58702850341797,-20.83675765991211,-20.32892417907715,-20.9426212310791,-20.2777099609375,-20.545957565307617,-20.586647033691406,-20.52328872680664,-20.63448143005371,-20.782262802124023,-20.538639068603516,-20.50191879272461,-20.6893367767334,-20.783708572387695,-20.636138916015625,-20.530601501464844,-20.842098236083984,-20.64483070373535,-20.445892333984375,-20.61720848083496,-20.787181854248047],"y":[7.2256317138671875,8.104182243347168,9.033221244812012,8.6190185546875,10.313775062561035,7.353267192840576,10.255369186401367,8.868692398071289,9.2672119140625,9.687627792358398,9.729890823364258,9.445578575134277,7.443373203277588,8.756508827209473,8.775127410888672,7.817134380340576,6.755746841430664,7.969846248626709,9.068931579589844,8.832085609436035,8.975539207458496,8.18820858001709,8.085362434387207,10.507521629333496,7.338778972625732,8.554498672485352,9.64892578125,8.901745796203613,9.20203685760498,7.609713554382324,7.630095481872559,8.400850296020508,9.10696792602539,10.309057235717773,10.663805961608887,8.651876449584961,9.464672088623047,10.137813568115234,8.637187957763672,7.587926864624023,9.302690505981445,8.356524467468262,8.744139671325684,9.621293067932129,9.17807388305664,9.166963577270508,10.1862211227417,8.740751266479492,9.301220893859863,9.5281982421875,9.49656867980957,9.858721733093262,10.278217315673828,8.789064407348633,10.134100914001465,9.472086906433105,9.576388359069824,9.385153770446777,8.043092727661133,8.362943649291992,9.011845588684082,9.0858736038208,10.698199272155762,8.210114479064941,10.190516471862793,10.073504447937012,8.902125358581543,8.848060607910156,9.257384300231934,7.211284160614014,8.220056533813477,9.627530097961426,9.200722694396973,9.146556854248047,8.731878280639648,9.259912490844727,10.16260051727295,9.247187614440918,9.519989013671875,9.493480682373047,10.005945205688477,10.017602920532227,10.071650505065918,8.347029685974121,8.579901695251465,10.696531295776367,8.807307243347168,9.937034606933594,7.542530059814453,8.162178039550781,9.59508228302002,10.051416397094727,9.363417625427246,9.002099990844727,8.906852722167969,9.887185096740723,9.590814590454102,9.152020454406738,9.256318092346191,8.288727760314941,8.490878105163574,9.601003646850586,9.033356666564941,9.186213493347168,9.555365562438965,9.03641128540039,8.373056411743164,10.676054954528809,9.1109619140625,8.125086784362793,8.70898151397705,7.650249004364014,9.138425827026367,8.904583930969238,8.859886169433594,9.72614574432373,10.077736854553223,9.753023147583008,8.714378356933594,8.931958198547363,7.574357986450195,9.301105499267578,10.814144134521484,9.410229682922363,9.131109237670898,9.859777450561523,8.045750617980957,9.450267791748047,9.066208839416504,8.55534553527832,9.637022018432617,8.648679733276367,6.7361531257629395,7.944613456726074,10.111549377441406,10.413093566894531,9.676403999328613,9.15366268157959,8.94932746887207,8.67009162902832,9.265515327453613,9.107481002807617,9.519648551940918,9.810458183288574,7.956625461578369,9.247211456298828,9.506261825561523,8.108312606811523,9.617596626281738,8.906185150146484,9.577478408813477,9.174176216125488,8.2438325881958,9.739182472229004,9.195253372192383,9.574718475341797,9.064215660095215,9.191932678222656,9.526179313659668,8.685494422912598,9.42272663116455,9.958285331726074,9.659172058105469,9.657454490661621,7.506146430969238,8.485584259033203,8.117891311645508,9.454154014587402,9.14510440826416,10.276145935058594,8.584497451782227,9.17592716217041,8.99528694152832,9.413269996643066,9.423568725585938,9.005121231079102,9.069336891174316,8.55238151550293,8.372986793518066,9.535090446472168,8.348658561706543,9.502374649047852,8.782506942749023,9.652751922607422,9.808199882507324,9.003049850463867,9.175460815429688,8.721566200256348,8.858457565307617,8.961238861083984,9.414812088012695,9.284849166870117,8.470803260803223,9.259923934936523,9.063225746154785,9.68591594696045,8.809160232543945,8.858317375183105,9.548007011413574,8.874265670776367,9.18164348602295,8.99881362915039,9.230653762817383,8.911385536193848,9.415619850158691,8.794425964355469,8.886189460754395,9.408085823059082,8.936629295349121,8.556017875671387,8.556697845458984,9.348644256591797,9.281595230102539,9.123262405395508,8.452258110046387,9.39798355102539,9.302046775817871,9.057232856750488,9.117193222045898,9.20361328125,8.933989524841309,8.919054985046387,8.84107494354248,8.7691068649292,9.194084167480469,9.348563194274902,9.257110595703125,8.880829811096191,9.102998733520508,9.201521873474121,8.787932395935059,9.205097198486328,8.85053825378418,8.980189323425293,8.953681945800781,8.88115119934082,9.092490196228027,9.145739555358887,9.28415298461914,9.155049324035645,9.170158386230469,8.847702980041504,9.243980407714844,9.105581283569336,9.158219337463379,9.028870582580566,9.61939525604248,9.12137222290039,9.15006160736084,8.691591262817383],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"#FFA15A","size":3},"mode":"markers","name":"cluster 4","x":[-9.175098419189453,-10.717755317687988,-10.7408447265625,-9.825562477111816,-9.397467613220215,-10.646347045898438,-7.336914539337158,-9.548205375671387,-10.116873741149902,-8.301310539245605,-11.40233325958252,-8.961999893188477,-10.077349662780762,-9.31166934967041,-9.989248275756836,-10.774120330810547,-8.626992225646973,-10.782404899597168,-11.10830020904541,-9.084687232971191,-10.011663436889648,-10.077661514282227,-9.362349510192871,-10.226461410522461,-9.062236785888672,-10.098777770996094,-11.515318870544434,-12.371634483337402,-9.725398063659668,-8.770848274230957,-7.765513896942139,-9.943249702453613,-9.1072998046875,-9.448599815368652,-9.338797569274902,-10.36954402923584,-8.748248100280762,-10.377517700195312,-8.477592468261719,-7.9042253494262695,-9.43204402923584,-9.197310447692871,-9.248035430908203,-10.749789237976074,-6.970077991485596,-10.202052116394043,-9.183168411254883,-9.125622749328613,-9.967028617858887,-10.901350021362305,-9.933403015136719,-8.769031524658203,-11.039146423339844,-10.57817268371582,-9.166353225708008,-8.998565673828125,-10.0382661819458,-9.174529075622559,-9.406189918518066,-9.084136009216309,-10.929821968078613,-9.890791893005371,-9.930784225463867,-10.498824119567871,-9.786796569824219,-9.215559959411621,-10.625301361083984,-10.53876781463623,-8.862016677856445,-8.823416709899902,-9.686357498168945,-9.986945152282715,-9.036998748779297,-9.111833572387695,-8.315607070922852,-9.346155166625977,-9.720320701599121,-10.591472625732422,-13.03564167022705,-9.34222412109375,-9.235370635986328,-9.610761642456055,-9.218552589416504,-9.25324535369873,-9.70505142211914,-11.558961868286133,-12.639104843139648,-9.38034439086914,-10.418858528137207,-9.368457794189453,-9.509930610656738,-10.43272590637207,-9.932083129882812,-10.26479434967041,-9.704931259155273,-9.111907958984375,-8.763924598693848,-9.133013725280762,-8.821572303771973,-9.536039352416992,-10.018610954284668,-10.536450386047363,-9.615033149719238,-8.440199851989746,-9.8569917678833,-9.023401260375977,-8.267629623413086,-9.044642448425293,-9.120975494384766,-9.554506301879883,-10.756781578063965,-9.217758178710938,-8.62641429901123,-10.037647247314453,-9.242051124572754,-9.539534568786621,-9.06312084197998,-10.220621109008789,-10.061826705932617,-10.096446990966797,-9.799175262451172,-9.811711311340332,-9.398355484008789,-9.487215042114258,-10.136751174926758,-9.944677352905273,-9.757410049438477,-9.928571701049805,-9.539491653442383,-9.559473991394043,-10.620015144348145,-9.098170280456543,-10.259286880493164,-9.621068000793457,-10.139092445373535,-9.4721040725708,-9.4095458984375,-9.338305473327637,-10.614083290100098,-9.85672664642334,-9.646906852722168,-9.788751602172852,-9.609505653381348,-8.73305606842041,-9.815840721130371,-10.04177188873291,-9.08619499206543,-10.09001636505127,-10.027653694152832,-9.611071586608887,-8.868733406066895,-9.192733764648438,-9.52587890625,-9.133888244628906,-9.363636016845703,-8.621373176574707,-9.46953296661377,-9.934414863586426,-9.63073444366455,-8.688777923583984,-9.499287605285645,-9.286190032958984,-9.116972923278809,-9.201835632324219,-10.351069450378418,-10.099514961242676,-9.245187759399414,-8.956608772277832,-10.06017780303955,-10.050618171691895,-9.471384048461914,-9.83533000946045,-9.910028457641602,-9.784523963928223,-9.346548080444336,-9.700675010681152,-8.812723159790039,-8.975417137145996,-9.909649848937988,-9.589932441711426,-9.50031852722168,-9.663724899291992,-9.65188980102539,-9.730910301208496,-10.293015480041504,-9.632843971252441,-9.510324478149414,-10.093289375305176,-9.754948616027832,-9.474019050598145,-9.74553394317627,-9.63035774230957,-9.338532447814941,-9.709052085876465,-9.49512004852295,-9.669843673706055,-8.981581687927246,-9.373250961303711,-10.198868751525879,-9.321281433105469,-9.311895370483398,-9.146393775939941,-9.42107105255127,-9.625249862670898,-9.354472160339355,-9.697728157043457,-9.315248489379883,-9.540663719177246,-9.924131393432617,-10.061517715454102,-9.868688583374023,-9.777600288391113,-9.624924659729004,-9.710868835449219,-9.592975616455078,-9.933387756347656,-9.525656700134277,-9.726227760314941,-9.821043014526367,-9.58070182800293,-9.368002891540527,-9.747201919555664,-9.65095329284668,-9.513349533081055,-9.742878913879395,-9.726753234863281,-9.728856086730957,-9.48227310180664,-9.803766250610352,-9.692222595214844,-9.537939071655273,-9.602463722229004,-9.859869956970215,-9.030158042907715,-9.58510684967041,-9.801671981811523,-9.565423965454102,-10.010437965393066,-9.474167823791504,-10.031205177307129,-9.959671974182129,-9.555570602416992,-9.658638000488281,-9.909643173217773,-9.795968055725098,-9.540325164794922,-9.696059226989746,-9.645999908447266,-9.540096282958984,-9.83711051940918],"y":[23.710058212280273,24.43324089050293,24.795997619628906,25.16341781616211,23.170011520385742,25.872957229614258,23.684833526611328,24.249235153198242,25.272579193115234,25.49187469482422,25.39481544494629,24.647607803344727,23.533796310424805,24.583162307739258,24.500953674316406,24.1849308013916,26.018817901611328,24.956989288330078,22.14016342163086,25.156862258911133,24.26142692565918,24.99610710144043,24.637964248657227,24.748079299926758,25.3625545501709,24.881990432739258,24.23975944519043,24.6248722076416,25.223352432250977,23.354494094848633,26.695430755615234,24.560428619384766,24.603057861328125,24.47547721862793,23.20952606201172,25.335033416748047,24.7179012298584,24.23316192626953,23.092309951782227,25.51896858215332,23.071712493896484,22.9283504486084,25.010053634643555,24.363252639770508,24.047426223754883,24.24999237060547,26.069257736206055,23.736040115356445,23.85849952697754,25.40026092529297,24.586523056030273,25.859458923339844,22.820064544677734,24.960609436035156,25.006601333618164,22.906360626220703,25.51313591003418,23.799041748046875,24.84244728088379,25.714622497558594,24.469635009765625,25.534975051879883,24.694442749023438,24.90806770324707,23.809085845947266,24.133289337158203,25.396089553833008,24.344139099121094,23.183015823364258,24.58610725402832,25.925432205200195,26.04290199279785,24.57356071472168,25.443910598754883,22.61597442626953,22.986825942993164,24.452531814575195,23.28824806213379,23.566495895385742,24.046581268310547,26.400564193725586,24.894315719604492,24.533279418945312,23.946266174316406,24.017976760864258,23.92085838317871,23.507776260375977,25.693037033081055,22.91983985900879,23.51136589050293,25.10570526123047,25.317899703979492,24.076757431030273,25.097082138061523,24.560653686523438,25.16246223449707,23.90807342529297,24.780179977416992,23.832862854003906,24.878578186035156,25.41362190246582,24.5897274017334,24.196279525756836,23.84842872619629,24.94614601135254,22.327674865722656,23.59037208557129,24.327804565429688,24.608722686767578,24.280227661132812,24.29016876220703,24.889822006225586,24.69334602355957,24.370513916015625,24.94923210144043,24.654144287109375,23.66114044189453,24.595149993896484,22.97499656677246,24.062959671020508,24.72875213623047,23.807836532592773,24.91436004638672,24.994070053100586,24.98936653137207,24.284950256347656,24.19437026977539,23.763452529907227,22.95223617553711,23.93189239501953,23.884965896606445,24.963863372802734,24.561447143554688,23.500019073486328,25.182693481445312,24.906776428222656,24.69207763671875,24.272945404052734,23.919048309326172,24.467554092407227,24.465314865112305,24.9495849609375,24.171907424926758,24.253385543823242,24.603984832763672,23.362285614013672,25.255170822143555,25.27802848815918,24.705366134643555,26.611469268798828,25.203481674194336,24.6695613861084,23.863292694091797,25.096275329589844,25.221473693847656,24.631263732910156,25.73703384399414,24.309228897094727,24.689516067504883,27.19931411743164,24.60065460205078,23.701120376586914,24.21457862854004,25.09558868408203,24.697246551513672,24.299463272094727,24.173175811767578,24.251108169555664,24.338956832885742,24.974618911743164,24.563060760498047,24.682785034179688,24.50143051147461,24.550458908081055,24.61911964416504,24.591323852539062,24.239110946655273,25.48885726928711,24.407024383544922,24.909337997436523,24.62091827392578,23.78009796142578,25.698564529418945,24.8376407623291,24.553897857666016,25.60927963256836,24.719947814941406,24.838123321533203,24.699499130249023,24.432140350341797,24.70245361328125,24.762388229370117,24.056331634521484,25.13194465637207,24.60988426208496,24.758413314819336,24.47227668762207,25.094308853149414,24.82457160949707,24.871644973754883,24.061965942382812,24.754112243652344,24.519004821777344,24.383939743041992,24.84247589111328,24.64813804626465,24.335845947265625,24.209604263305664,24.525726318359375,24.355989456176758,23.73869514465332,24.6325740814209,24.583799362182617,24.22361183166504,24.347869873046875,24.02756118774414,24.216903686523438,24.665081024169922,24.609424591064453,24.299917221069336,24.36672019958496,24.35761070251465,24.32428741455078,24.726511001586914,24.295047760009766,24.418365478515625,23.82111358642578,24.500974655151367,24.407066345214844,24.543062210083008,24.28166961669922,24.056516647338867,24.578514099121094,24.361186981201172,24.707061767578125,24.6155948638916,24.422927856445312,24.513254165649414,24.7176570892334,24.694717407226562,24.275135040283203,24.429540634155273,24.618513107299805,24.414871215820312,24.2330379486084,24.40799903869629,24.2686767578125,24.300193786621094,24.373701095581055,24.3053035736084],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"#19D3F3","size":3},"mode":"markers","name":"cluster 5","x":[24.910682678222656,25.34837532043457,25.494184494018555,25.408140182495117,25.74078941345215,23.83885955810547,22.813547134399414,23.363483428955078,25.388933181762695,25.98965072631836,23.901628494262695,25.478534698486328,25.47199821472168,23.837371826171875,23.657665252685547,24.63673973083496,24.068674087524414,24.411540985107422,26.1698055267334,23.47989273071289,23.017940521240234,24.803813934326172,26.22003173828125,26.07416534423828,26.27798843383789,26.543569564819336,24.559534072875977,23.50326919555664,24.189306259155273,23.828121185302734,24.962146759033203,23.668075561523438,25.90069007873535,25.856647491455078,25.04754638671875,24.672115325927734,25.376188278198242,23.3994083404541,24.888946533203125,24.46791648864746,25.646318435668945,24.234928131103516,25.65432357788086,24.73572540283203,26.877452850341797,26.117982864379883,24.987096786499023,24.29631233215332,25.401424407958984,25.020214080810547,25.8836727142334,24.428821563720703,23.87449836730957,24.65486717224121,25.352203369140625,25.915632247924805,25.39487648010254,24.647233963012695,22.975290298461914,23.239742279052734,24.984115600585938,24.712488174438477,23.996139526367188,26.693603515625,24.025634765625,24.839818954467773,24.144197463989258,25.144990921020508,25.444503784179688,25.584253311157227,24.521610260009766,24.065507888793945,24.800579071044922,25.656003952026367,25.83521842956543,26.130943298339844,24.92086410522461,24.65412139892578,24.81186294555664,24.50841522216797,23.878917694091797,26.509536743164062,26.301847457885742,24.081932067871094,25.725841522216797,25.186769485473633,24.675172805786133,24.590234756469727,24.37795066833496,25.930919647216797,25.710983276367188,24.244421005249023,24.15072250366211,24.367544174194336,24.641538619995117,23.67178726196289,23.161685943603516,23.520572662353516,24.410602569580078,24.916532516479492,24.890033721923828,23.886411666870117,26.092714309692383,24.54050064086914,24.981550216674805,24.172693252563477,24.978130340576172,25.711181640625,24.142019271850586,24.685436248779297,25.699350357055664,25.078319549560547,25.67513084411621,25.66796112060547,25.237537384033203,25.013782501220703,25.03319549560547,23.611997604370117,24.284704208374023,23.925212860107422,24.04848861694336,24.822988510131836,25.14019012451172,25.3501033782959,24.893646240234375,24.789142608642578,24.778474807739258,25.277503967285156,25.021411895751953,25.31070327758789,25.764375686645508,24.74236297607422,24.936641693115234,22.907270431518555,23.85567855834961,25.038972854614258,24.384523391723633,25.080646514892578,25.037734985351562,25.258071899414062,26.839340209960938,25.282211303710938,25.388198852539062,24.149063110351562,25.157573699951172,26.05790138244629,25.064899444580078,24.958866119384766,25.540563583374023,26.351238250732422,25.037899017333984,25.30221939086914,24.47853660583496,25.102367401123047,25.148521423339844,25.222801208496094,24.496145248413086,25.0157470703125,25.16286277770996,24.879844665527344,25.366714477539062,24.85443878173828,24.53191566467285,25.43533706665039,24.994766235351562,23.769058227539062,25.2760009765625,25.088224411010742,25.325231552124023,25.60109519958496,24.64547348022461,24.60275650024414,25.1983585357666,24.285816192626953,24.30204200744629,24.848228454589844,23.952062606811523,25.25889778137207,25.27179718017578,25.291688919067383,24.345888137817383,24.7900447845459,24.807729721069336,25.947725296020508,24.91465950012207,25.15658187866211,24.271800994873047,23.660350799560547,25.955970764160156,24.332279205322266,24.965511322021484,25.173704147338867,25.64960479736328,24.97909927368164,24.774723052978516,25.038572311401367,25.188486099243164,22.478212356567383,24.33395004272461,24.540170669555664,25.13083839416504,25.080825805664062,24.868534088134766,24.51236343383789,24.6473331451416,24.49964141845703,24.698883056640625,25.152746200561523,24.24199676513672,24.929502487182617,23.748004913330078,24.994808197021484,24.721385955810547,24.904048919677734,25.014171600341797,24.94476318359375,25.728544235229492,24.029537200927734,24.714672088623047,24.243457794189453,25.209611892700195,25.02591323852539,25.004838943481445,24.87017822265625,25.14804458618164,24.787355422973633,26.234210968017578,24.778642654418945,25.30437469482422,25.26657485961914,24.799535751342773,25.046226501464844,24.437517166137695,24.27277183532715,24.340553283691406,25.133132934570312,26.236005783081055,24.46912384033203,24.46790313720703,25.260467529296875,24.747774124145508,24.734188079833984,24.830575942993164,25.19755744934082,24.624177932739258,25.088563919067383,24.41775131225586,24.955820083618164,23.681716918945312,24.81907081604004],"y":[3.330777645111084,6.020845413208008,4.878580093383789,2.8338797092437744,3.5333807468414307,3.52543568611145,3.8547966480255127,3.6168577671051025,3.4764564037323,3.4904544353485107,4.256732940673828,3.976310968399048,3.678469181060791,3.235539674758911,6.464766502380371,4.962484836578369,3.3197004795074463,3.1321396827697754,3.632070779800415,3.9715092182159424,3.41865873336792,2.0345215797424316,3.0893375873565674,4.786351680755615,2.462409019470215,1.6646146774291992,2.749504804611206,4.42903470993042,5.338466644287109,2.824512243270874,3.8982300758361816,3.3813071250915527,3.0815906524658203,2.5399129390716553,6.573952674865723,1.837752103805542,3.511606216430664,4.024438381195068,4.868908882141113,3.2962446212768555,2.9057390689849854,2.805698871612549,3.6049845218658447,3.25842547416687,4.82144832611084,3.0124621391296387,3.281636953353882,3.3958561420440674,3.9205336570739746,4.37310791015625,2.529381036758423,3.82352876663208,4.100802421569824,4.146665573120117,3.6993343830108643,4.0426836013793945,3.8813552856445312,3.0787765979766846,3.803394079208374,3.9275927543640137,5.91271448135376,4.586258411407471,5.098888397216797,4.892326354980469,3.41054368019104,3.6226184368133545,2.6303484439849854,2.1262729167938232,3.335902214050293,2.268951416015625,2.6626029014587402,4.5427727699279785,4.160868167877197,1.6258630752563477,2.797292470932007,2.8907880783081055,3.2135725021362305,3.819002151489258,2.70746111869812,3.72809100151062,2.586568593978882,4.622387409210205,3.723752737045288,3.9004955291748047,3.276989698410034,2.734090566635132,2.885084629058838,4.1009602546691895,3.6543407440185547,5.030605792999268,3.806281328201294,3.813194751739502,2.9819729328155518,4.797334671020508,3.8813045024871826,3.8296658992767334,3.62540864944458,2.6916279792785645,3.8562448024749756,3.763993740081787,3.523939609527588,3.3996074199676514,3.9696998596191406,3.4673898220062256,3.7388296127319336,4.767340183258057,2.6602582931518555,3.509841203689575,4.655098915100098,2.8114421367645264,2.9762070178985596,2.728975296020508,4.370626926422119,4.790633201599121,3.56282114982605,4.182356834411621,3.5906481742858887,4.567654132843018,3.2082290649414062,3.890040636062622,3.9749374389648438,3.5927751064300537,4.164626598358154,3.7241098880767822,3.4116556644439697,3.930419921875,4.261638164520264,3.225705623626709,3.5172252655029297,2.0944671630859375,4.157174587249756,3.839304208755493,3.8039438724517822,4.4080634117126465,3.770552635192871,2.145508050918579,4.092597961425781,3.801905393600464,3.2953319549560547,2.843958854675293,4.4487199783325195,3.022264003753662,2.7801220417022705,4.452047348022461,3.3042337894439697,4.009010314941406,3.7784042358398438,4.667141914367676,3.8133888244628906,4.493534564971924,3.432889938354492,3.930741786956787,3.51332426071167,3.3434717655181885,3.726921558380127,3.749544143676758,3.747199535369873,3.3442540168762207,3.4547338485717773,3.767911911010742,3.69343900680542,3.5153822898864746,2.7231061458587646,3.594784736633301,3.4222238063812256,4.074202537536621,4.30111026763916,2.9396867752075195,3.626936674118042,3.214691162109375,3.8465402126312256,3.774789571762085,3.9104104042053223,3.846642255783081,4.45501184463501,3.5922789573669434,3.978299617767334,3.315298557281494,3.9734203815460205,3.9141037464141846,4.051689624786377,3.4735729694366455,3.352191925048828,4.089845180511475,3.5766139030456543,3.494675636291504,3.529463052749634,7.438138484954834,3.2793750762939453,3.582956552505493,3.504197120666504,3.6885392665863037,4.113337993621826,4.597172737121582,3.234827995300293,3.2660911083221436,3.5961191654205322,4.674903392791748,4.20421838760376,3.6127467155456543,3.3207662105560303,3.681143283843994,3.495551347732544,3.6696832180023193,3.710374116897583,3.9555327892303467,3.4842352867126465,3.737847089767456,3.9540481567382812,3.211207628250122,4.1135406494140625,3.6313412189483643,3.6113667488098145,3.4984922409057617,3.313113212585449,3.3840832710266113,4.988737106323242,4.024889945983887,3.5050787925720215,4.104426383972168,3.7113656997680664,3.671146869659424,3.7105963230133057,3.733858346939087,3.8169031143188477,3.586338520050049,4.958096027374268,3.747741937637329,4.087501049041748,3.963080883026123,3.5867626667022705,3.384695053100586,3.834385871887207,3.974574327468872,3.6760823726654053,4.200450420379639,4.56597900390625,4.28107213973999,3.998521089553833,3.4731554985046387,3.6298670768737793,3.876680374145508,3.6756393909454346,3.6349637508392334,3.878059148788452,3.6902849674224854,3.8119218349456787,3.9618678092956543,3.8003382682800293,4.274758338928223],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"}],                        {"template":{"data":{"scatter":[{"marker":{"color":"#d92310"},"type":"scatter"}]},"layout":{"height":576,"paper_bgcolor":"#fcfcfc","plot_bgcolor":"#fcfcfc","width":1024}},"xaxis":{"zeroline":false},"yaxis":{"zeroline":false}},                        {"responsive": true}                    ).then(function(){
                            
var gd = document.getElementById('97c097a6-2f4e-4227-a94a-c9f7c4f3008d');
var x = new MutationObserver(function (mutations, observer) {{
        var display = window.getComputedStyle(gd).display;
        if (!display || display === 'none') {{
            console.log([gd, 'removed!']);
            Plotly.purge(gd);
            observer.disconnect();
        }}
}});

// Listen for the removal of the full notebook cells
var notebookContainer = gd.closest('#notebook-container');
if (notebookContainer) {{
    x.observe(notebookContainer, {childList: true});
}}

// Listen for the clearing of the current output cell
var outputEl = gd.closest('.output');
if (outputEl) {{
    x.observe(outputEl, {childList: true});
}}

                        })                };                });            </script>        </div>
</div>
</div>
<div id="b318d0bb" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb75" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb75-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> update(X):</span>
<span id="cb75-2">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, n, bs):</span>
<span id="cb75-3">    s <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">slice</span>(i, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">min</span>(i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>bs, n))</span>
<span id="cb75-4">    dists <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (X[s][:, <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, :] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> X[<span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">None</span>, ...]).square().<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=-</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>).sqrt()</span>
<span id="cb75-5">    ws <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> egauss_kernel(dists, mean<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, std<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">2.5</span>)</span>
<span id="cb75-6">    X[s] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> (ws <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">@</span> X) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> ws.<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">sum</span>(dim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, keepdim<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>)</span>
<span id="cb75-7"></span>
<span id="cb75-8"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> meanshift(data):</span>
<span id="cb75-9">   X <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> data.clone()</span>
<span id="cb75-10">   <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>): update(X)</span>
<span id="cb75-11">   <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> X</span></code></pre></div></div>
</div>
<div id="010b0677" class="cell page-columns page-full">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb76" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb76-1">plot_data(centroids<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, meanshift(data), n_samples)</span></code></pre></div></div>
<div class="cell-output cell-output-display column-page">
<div>                            <div id="5c5d978c-ac2f-4917-97a3-f419c75301c0" class="plotly-graph-div" style="height:576px; width:1024px;"></div>            <script type="text/javascript">                require(["plotly"], function(Plotly) {                    window.PLOTLYENV=window.PLOTLYENV || {};                                    if (document.getElementById("5c5d978c-ac2f-4917-97a3-f419c75301c0")) {                    Plotly.newPlot(                        "5c5d978c-ac2f-4917-97a3-f419c75301c0",                        [{"marker":{"color":"#636EFA","size":3},"mode":"markers","name":"cluster 0","x":[2.579368829727173,2.579368829727173,2.579368829727173,2.579368829727173,2.579368829727173,2.579368829727173,2.579368829727173,2.579368829727173,2.5793724060058594,2.5793724060058594,2.5793724060058594,2.5793724060058594,2.5793724060058594,2.5793724060058594,2.5793724060058594,2.5793724060058594,2.579371929168701,2.579371929168701,2.579371929168701,2.579371929168701,2.579371929168701,2.579371929168701,2.579371929168701,2.579371929168701,2.5793673992156982,2.5793673992156982,2.5793673992156982,2.5793673992156982,2.5793673992156982,2.5793673992156982,2.5793673992156982,2.5793673992156982,2.5793607234954834,2.5793607234954834,2.5793607234954834,2.5793607234954834,2.5793607234954834,2.5793607234954834,2.5793607234954834,2.5793607234954834,2.5793521404266357,2.5793521404266357,2.5793521404266357,2.5793521404266357,2.5793521404266357,2.5793521404266357,2.5793521404266357,2.5793521404266357,2.579342842102051,2.579342842102051,2.579342842102051,2.579342842102051,2.579342842102051,2.579342842102051,2.579342842102051,2.579342842102051,2.579334020614624,2.579334020614624,2.579334020614624,2.579334020614624,2.579334020614624,2.579334020614624,2.579334020614624,2.579334020614624,2.5793256759643555,2.5793256759643555,2.5793256759643555,2.5793256759643555,2.5793256759643555,2.5793256759643555,2.5793256759643555,2.5793256759643555,2.579318046569824,2.579318046569824,2.579318046569824,2.579318046569824,2.579318046569824,2.579318046569824,2.579318046569824,2.579318046569824,2.5793113708496094,2.5793113708496094,2.5793113708496094,2.5793113708496094,2.5793113708496094,2.5793113708496094,2.5793113708496094,2.5793113708496094,2.579306125640869,2.579306125640869,2.579306125640869,2.579306125640869,2.579306125640869,2.579306125640869,2.579306125640869,2.579306125640869,2.579301595687866,2.579301595687866,2.579301595687866,2.579301595687866,2.579301595687866,2.579301595687866,2.579301595687866,2.579301595687866,2.5792977809906006,2.5792977809906006,2.5792977809906006,2.5792977809906006,2.5792977809906006,2.5792977809906006,2.5792977809906006,2.5792977809906006,2.5792949199676514,2.5792949199676514,2.5792949199676514,2.5792949199676514,2.5792949199676514,2.5792949199676514,2.5792949199676514,2.5792949199676514,2.579293966293335,2.579293966293335,2.579293966293335,2.579293966293335,2.579293966293335,2.579293966293335,2.579293966293335,2.579293966293335,2.579294204711914,2.579294204711914,2.579294204711914,2.579294204711914,2.579294204711914,2.579294204711914,2.579294204711914,2.579294204711914,2.5792958736419678,2.5792958736419678,2.5792958736419678,2.5792958736419678,2.5792958736419678,2.5792958736419678,2.5792958736419678,2.5792958736419678,2.579298496246338,2.579298496246338,2.579298496246338,2.579298496246338,2.579298496246338,2.579298496246338,2.579298496246338,2.579298496246338,2.579301595687866,2.579301595687866,2.579301595687866,2.579301595687866,2.579301595687866,2.579301595687866,2.579301595687866,2.579301595687866,2.5793051719665527,2.5793051719665527,2.5793051719665527,2.5793051719665527,2.5793051719665527,2.5793051719665527,2.5793051719665527,2.5793051719665527,2.5793089866638184,2.5793089866638184,2.5793089866638184,2.5793089866638184,2.5793089866638184,2.5793089866638184,2.5793089866638184,2.5793089866638184,2.5793120861053467,2.5793120861053467,2.5793120861053467,2.5793120861053467,2.5793120861053467,2.5793120861053467,2.5793120861053467,2.5793120861053467,2.579315185546875,2.579315185546875,2.579315185546875,2.579315185546875,2.579315185546875,2.579315185546875,2.579315185546875,2.579315185546875,2.579317331314087,2.579317331314087,2.579317331314087,2.579317331314087,2.579317331314087,2.579317331314087,2.579317331314087,2.579317331314087,2.579319715499878,2.579319715499878,2.579319715499878,2.579319715499878,2.579319715499878,2.579319715499878,2.579319715499878,2.579319715499878,2.5793211460113525,2.5793211460113525,2.5793211460113525,2.5793211460113525,2.5793211460113525,2.5793211460113525,2.5793211460113525,2.5793211460113525,2.579322099685669,2.579322099685669,2.579322099685669,2.579322099685669,2.579322099685669,2.579322099685669,2.579322099685669,2.579322099685669,2.5793235301971436,2.5793235301971436,2.5793235301971436,2.5793235301971436,2.5793235301971436,2.5793235301971436,2.5793235301971436,2.5793235301971436,2.579324245452881,2.579324245452881,2.579324245452881,2.579324245452881,2.579324245452881,2.579324245452881,2.579324245452881,2.579324245452881,2.579324245452881,2.579324245452881,2.579324245452881,2.579324245452881,2.579324245452881,2.579324245452881,2.579324245452881,2.579324245452881,2.5793235301971436,2.5793235301971436],"y":[-21.179954528808594,-21.179954528808594,-21.179954528808594,-21.179954528808594,-21.179954528808594,-21.179954528808594,-21.179948806762695,-21.179948806762695,-21.179941177368164,-21.179941177368164,-21.179941177368164,-21.179941177368164,-21.179941177368164,-21.179941177368164,-21.179933547973633,-21.179933547973633,-21.179929733276367,-21.179929733276367,-21.179929733276367,-21.179929733276367,-21.179929733276367,-21.179929733276367,-21.1799259185791,-21.1799259185791,-21.179920196533203,-21.179920196533203,-21.179920196533203,-21.179920196533203,-21.179920196533203,-21.179920196533203,-21.179916381835938,-21.179916381835938,-21.179912567138672,-21.179912567138672,-21.179912567138672,-21.179912567138672,-21.179912567138672,-21.179912567138672,-21.179906845092773,-21.179906845092773,-21.179906845092773,-21.179906845092773,-21.179906845092773,-21.179906845092773,-21.179906845092773,-21.179906845092773,-21.179901123046875,-21.179901123046875,-21.179903030395508,-21.179903030395508,-21.179903030395508,-21.179903030395508,-21.179903030395508,-21.179903030395508,-21.17989730834961,-21.17989730834961,-21.179901123046875,-21.179901123046875,-21.179901123046875,-21.179901123046875,-21.179901123046875,-21.179901123046875,-21.179895401000977,-21.179895401000977,-21.179901123046875,-21.179901123046875,-21.179901123046875,-21.179901123046875,-21.179901123046875,-21.179901123046875,-21.179895401000977,-21.179895401000977,-21.179903030395508,-21.179903030395508,-21.179903030395508,-21.179903030395508,-21.179903030395508,-21.179903030395508,-21.17989730834961,-21.17989730834961,-21.17991065979004,-21.17991065979004,-21.17991065979004,-21.17991065979004,-21.17991065979004,-21.17991065979004,-21.179903030395508,-21.179903030395508,-21.179916381835938,-21.179916381835938,-21.179916381835938,-21.179916381835938,-21.179916381835938,-21.179916381835938,-21.17991065979004,-21.17991065979004,-21.179922103881836,-21.179922103881836,-21.179922103881836,-21.179922103881836,-21.179922103881836,-21.179922103881836,-21.179916381835938,-21.179916381835938,-21.179927825927734,-21.179927825927734,-21.179927825927734,-21.179927825927734,-21.179927825927734,-21.179927825927734,-21.179922103881836,-21.179922103881836,-21.179933547973633,-21.179933547973633,-21.179933547973633,-21.179933547973633,-21.179933547973633,-21.179933547973633,-21.179927825927734,-21.179927825927734,-21.179941177368164,-21.179941177368164,-21.179941177368164,-21.179941177368164,-21.179941177368164,-21.179941177368164,-21.179933547973633,-21.179933547973633,-21.17994499206543,-21.17994499206543,-21.17994499206543,-21.17994499206543,-21.17994499206543,-21.17994499206543,-21.1799373626709,-21.1799373626709,-21.179950714111328,-21.179950714111328,-21.179950714111328,-21.179950714111328,-21.179950714111328,-21.179950714111328,-21.179943084716797,-21.179943084716797,-21.179954528808594,-21.179954528808594,-21.179954528808594,-21.179954528808594,-21.179954528808594,-21.179954528808594,-21.179946899414062,-21.179946899414062,-21.179956436157227,-21.179956436157227,-21.179956436157227,-21.179956436157227,-21.179956436157227,-21.179956436157227,-21.179948806762695,-21.179948806762695,-21.179956436157227,-21.179956436157227,-21.179956436157227,-21.179956436157227,-21.179956436157227,-21.179956436157227,-21.179948806762695,-21.179948806762695,-21.179956436157227,-21.179956436157227,-21.179956436157227,-21.179956436157227,-21.179956436157227,-21.179956436157227,-21.179948806762695,-21.179948806762695,-21.179956436157227,-21.179956436157227,-21.179956436157227,-21.179956436157227,-21.179956436157227,-21.179956436157227,-21.179948806762695,-21.179948806762695,-21.179950714111328,-21.179950714111328,-21.179950714111328,-21.179950714111328,-21.179950714111328,-21.179950714111328,-21.179948806762695,-21.179948806762695,-21.17994499206543,-21.17994499206543,-21.17994499206543,-21.17994499206543,-21.17994499206543,-21.17994499206543,-21.179941177368164,-21.179941177368164,-21.17993927001953,-21.17993927001953,-21.17993927001953,-21.17993927001953,-21.17993927001953,-21.17993927001953,-21.179935455322266,-21.179935455322266,-21.179933547973633,-21.179933547973633,-21.179933547973633,-21.179933547973633,-21.179933547973633,-21.179933547973633,-21.179929733276367,-21.179929733276367,-21.1799259185791,-21.1799259185791,-21.1799259185791,-21.1799259185791,-21.1799259185791,-21.1799259185791,-21.17992401123047,-21.17992401123047,-21.179920196533203,-21.179920196533203,-21.179920196533203,-21.179920196533203,-21.179920196533203,-21.179920196533203,-21.17991828918457,-21.17991828918457,-21.179914474487305,-21.179914474487305,-21.179914474487305,-21.179914474487305,-21.179914474487305,-21.179914474487305,-21.17991065979004,-21.17991065979004,-21.17991065979004,-21.17991065979004,-21.17991065979004,-21.17991065979004,-21.17991065979004,-21.17991065979004,-21.179906845092773,-21.179906845092773,-21.17991065979004,-21.17991065979004],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 0","showlegend":false,"x":[4.444576263427734],"y":[-19.083776473999023],"type":"scatter"},{"marker":{"color":"#EF553B","size":3},"mode":"markers","name":"cluster 1","x":[11.030989646911621,11.030989646911621,11.030989646911621,11.030989646911621,11.030989646911621,11.030989646911621,11.03095531463623,11.03095531463623,11.03095531463623,11.03095531463623,11.03095531463623,11.03095531463623,11.03095531463623,11.03095531463623,11.030916213989258,11.030916213989258,11.030916213989258,11.030916213989258,11.030916213989258,11.030916213989258,11.030917167663574,11.030917167663574,11.03088665008545,11.03088665008545,11.03088665008545,11.03088665008545,11.03088665008545,11.03088665008545,11.030887603759766,11.030887603759766,11.030865669250488,11.030865669250488,11.030865669250488,11.030865669250488,11.030865669250488,11.030865669250488,11.030866622924805,11.030866622924805,11.030850410461426,11.030850410461426,11.030850410461426,11.030850410461426,11.030850410461426,11.030850410461426,11.030851364135742,11.030851364135742,11.030839920043945,11.030839920043945,11.030839920043945,11.030839920043945,11.030839920043945,11.030839920043945,11.030839920043945,11.030839920043945,11.030834197998047,11.030834197998047,11.030834197998047,11.030834197998047,11.030834197998047,11.030834197998047,11.030834197998047,11.030834197998047,11.030832290649414,11.030832290649414,11.030832290649414,11.030832290649414,11.030832290649414,11.030832290649414,11.030832290649414,11.030832290649414,11.030834197998047,11.030834197998047,11.030834197998047,11.030834197998047,11.030834197998047,11.030834197998047,11.030834197998047,11.030834197998047,11.030838012695312,11.030838012695312,11.030838012695312,11.030838012695312,11.030838012695312,11.030838012695312,11.030838012695312,11.030838012695312,11.030843734741211,11.030843734741211,11.030843734741211,11.030843734741211,11.030843734741211,11.030843734741211,11.030843734741211,11.030843734741211,11.030851364135742,11.030851364135742,11.030851364135742,11.030851364135742,11.030851364135742,11.030851364135742,11.030851364135742,11.030851364135742,11.030858993530273,11.030858993530273,11.030858993530273,11.030858993530273,11.030858993530273,11.030858993530273,11.030858993530273,11.030858993530273,11.030866622924805,11.030866622924805,11.030866622924805,11.030866622924805,11.030866622924805,11.030866622924805,11.030866622924805,11.030866622924805,11.030874252319336,11.030874252319336,11.030874252319336,11.030874252319336,11.030874252319336,11.030874252319336,11.030874252319336,11.030874252319336,11.03088092803955,11.03088092803955,11.03088092803955,11.03088092803955,11.03088092803955,11.03088092803955,11.03088092803955,11.03088092803955,11.030888557434082,11.030888557434082,11.030888557434082,11.030888557434082,11.030888557434082,11.030888557434082,11.030888557434082,11.030888557434082,11.030896186828613,11.030896186828613,11.030896186828613,11.030896186828613,11.030896186828613,11.030896186828613,11.030896186828613,11.030896186828613,11.030903816223145,11.030903816223145,11.030903816223145,11.030903816223145,11.030903816223145,11.030903816223145,11.030903816223145,11.030903816223145,11.030913352966309,11.030913352966309,11.030913352966309,11.030913352966309,11.030913352966309,11.030913352966309,11.030913352966309,11.030913352966309,11.030919075012207,11.030919075012207,11.030919075012207,11.030919075012207,11.030919075012207,11.030919075012207,11.030919075012207,11.030919075012207,11.030924797058105,11.030924797058105,11.030924797058105,11.030924797058105,11.030924797058105,11.030924797058105,11.030924797058105,11.030924797058105,11.030928611755371,11.030928611755371,11.030928611755371,11.030928611755371,11.030928611755371,11.030928611755371,11.030928611755371,11.030928611755371,11.03093147277832,11.03093147277832,11.03093147277832,11.03093147277832,11.03093147277832,11.03093147277832,11.03093147277832,11.03093147277832,11.03093147277832,11.03093147277832,11.03093147277832,11.03093147277832,11.03093147277832,11.03093147277832,11.03093147277832,11.03093147277832,11.030928611755371,11.030928611755371,11.030928611755371,11.030928611755371,11.030928611755371,11.030928611755371,11.030928611755371,11.030928611755371,11.030924797058105,11.030924797058105,11.030924797058105,11.030924797058105,11.030924797058105,11.030924797058105,11.030924797058105,11.030924797058105,11.030919075012207,11.030919075012207,11.030919075012207,11.030919075012207,11.030919075012207,11.030919075012207,11.030919075012207,11.030919075012207,11.030913352966309,11.030913352966309,11.030913352966309,11.030913352966309,11.030913352966309,11.030913352966309,11.030913352966309,11.030913352966309,11.030906677246094,11.030906677246094,11.030906677246094,11.030906677246094,11.030906677246094,11.030906677246094,11.030906677246094,11.030906677246094,11.030903816223145,11.030903816223145,11.030903816223145,11.030903816223145],"y":[10.845463752746582,10.845463752746582,10.845463752746582,10.845463752746582,10.845463752746582,10.845463752746582,10.845474243164062,10.845474243164062,10.845474243164062,10.845474243164062,10.845474243164062,10.845474243164062,10.845474243164062,10.845474243164062,10.845489501953125,10.845489501953125,10.845489501953125,10.845489501953125,10.845489501953125,10.845489501953125,10.845489501953125,10.845489501953125,10.845503807067871,10.845503807067871,10.845503807067871,10.845503807067871,10.845503807067871,10.845503807067871,10.845500946044922,10.845500946044922,10.845515251159668,10.845515251159668,10.845515251159668,10.845515251159668,10.845515251159668,10.845515251159668,10.845512390136719,10.845512390136719,10.845523834228516,10.845523834228516,10.845523834228516,10.845523834228516,10.845523834228516,10.845523834228516,10.845520973205566,10.845520973205566,10.845532417297363,10.845532417297363,10.845532417297363,10.845532417297363,10.845532417297363,10.845532417297363,10.84553050994873,10.84553050994873,10.845541000366211,10.845541000366211,10.845541000366211,10.845541000366211,10.845541000366211,10.845541000366211,10.845538139343262,10.845538139343262,10.845547676086426,10.845547676086426,10.845547676086426,10.845547676086426,10.845547676086426,10.845547676086426,10.845545768737793,10.845545768737793,10.845553398132324,10.845553398132324,10.845553398132324,10.845553398132324,10.845553398132324,10.845553398132324,10.845550537109375,10.845550537109375,10.845559120178223,10.845559120178223,10.845559120178223,10.845559120178223,10.845559120178223,10.845559120178223,10.845556259155273,10.845556259155273,10.845561981201172,10.845561981201172,10.845561981201172,10.845561981201172,10.845561981201172,10.845561981201172,10.845559120178223,10.845559120178223,10.845562934875488,10.845562934875488,10.845562934875488,10.845562934875488,10.845562934875488,10.845562934875488,10.845561027526855,10.845561027526855,10.845562934875488,10.845562934875488,10.845562934875488,10.845562934875488,10.845562934875488,10.845562934875488,10.845561027526855,10.845561027526855,10.845561981201172,10.845561981201172,10.845561981201172,10.845561981201172,10.845561981201172,10.845561981201172,10.845559120178223,10.845559120178223,10.845560073852539,10.845560073852539,10.845560073852539,10.845560073852539,10.845560073852539,10.845560073852539,10.845558166503906,10.845558166503906,10.84555721282959,10.84555721282959,10.84555721282959,10.84555721282959,10.84555721282959,10.84555721282959,10.845555305480957,10.845555305480957,10.845552444458008,10.845552444458008,10.845552444458008,10.845552444458008,10.845552444458008,10.845552444458008,10.845550537109375,10.845550537109375,10.84554672241211,10.84554672241211,10.84554672241211,10.84554672241211,10.84554672241211,10.84554672241211,10.84554386138916,10.84554386138916,10.845540046691895,10.845540046691895,10.845540046691895,10.845540046691895,10.845540046691895,10.845540046691895,10.845538139343262,10.845538139343262,10.845534324645996,10.845534324645996,10.845534324645996,10.845534324645996,10.845534324645996,10.845534324645996,10.845531463623047,10.845531463623047,10.845527648925781,10.845527648925781,10.845527648925781,10.845527648925781,10.845527648925781,10.845527648925781,10.845525741577148,10.845525741577148,10.845521926879883,10.845521926879883,10.845521926879883,10.845521926879883,10.845521926879883,10.845521926879883,10.84552001953125,10.84552001953125,10.845516204833984,10.845516204833984,10.845516204833984,10.845516204833984,10.845516204833984,10.845516204833984,10.845516204833984,10.845516204833984,10.845512390136719,10.845512390136719,10.845512390136719,10.845512390136719,10.845512390136719,10.845512390136719,10.845512390136719,10.845512390136719,10.84550952911377,10.84550952911377,10.84550952911377,10.84550952911377,10.84550952911377,10.84550952911377,10.84550952911377,10.84550952911377,10.84550952911377,10.84550952911377,10.84550952911377,10.84550952911377,10.84550952911377,10.84550952911377,10.84550952911377,10.84550952911377,10.845512390136719,10.845512390136719,10.845512390136719,10.845512390136719,10.845512390136719,10.845512390136719,10.845512390136719,10.845512390136719,10.845519065856934,10.845519065856934,10.845519065856934,10.845519065856934,10.845519065856934,10.845519065856934,10.845519065856934,10.845519065856934,10.845524787902832,10.845524787902832,10.845524787902832,10.845524787902832,10.845524787902832,10.845524787902832,10.845524787902832,10.845524787902832,10.845527648925781,10.845527648925781,10.845527648925781,10.845527648925781,10.845527648925781,10.845527648925781,10.845527648925781,10.845527648925781,10.845531463623047,10.845531463623047,10.845531463623047,10.845531463623047],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 1","showlegend":false,"x":[13.144817352294922],"y":[12.982318878173828],"type":"scatter"},{"marker":{"color":"#00CC96","size":3},"mode":"markers","name":"cluster 2","x":[-18.720930099487305,-18.720930099487305,-18.720930099487305,-18.720930099487305,-18.72092056274414,-18.72092056274414,-18.72092056274414,-18.72092056274414,-18.72092056274414,-18.72092056274414,-18.72092056274414,-18.72092056274414,-18.720903396606445,-18.720903396606445,-18.720903396606445,-18.720903396606445,-18.720903396606445,-18.720903396606445,-18.720903396606445,-18.720903396606445,-18.720884323120117,-18.720884323120117,-18.720884323120117,-18.720884323120117,-18.720884323120117,-18.720884323120117,-18.720884323120117,-18.720884323120117,-18.720869064331055,-18.720869064331055,-18.720869064331055,-18.720869064331055,-18.720869064331055,-18.720869064331055,-18.720869064331055,-18.720869064331055,-18.720855712890625,-18.720855712890625,-18.720855712890625,-18.720855712890625,-18.720855712890625,-18.720855712890625,-18.720855712890625,-18.720855712890625,-18.72084617614746,-18.72084617614746,-18.72084617614746,-18.72084617614746,-18.72084617614746,-18.72084617614746,-18.72084617614746,-18.72084617614746,-18.72083854675293,-18.72083854675293,-18.72083854675293,-18.72083854675293,-18.72083854675293,-18.72083854675293,-18.72083854675293,-18.72083854675293,-18.72083282470703,-18.72083282470703,-18.72083282470703,-18.72083282470703,-18.72083282470703,-18.72083282470703,-18.72083282470703,-18.72083282470703,-18.7208309173584,-18.7208309173584,-18.7208309173584,-18.7208309173584,-18.7208309173584,-18.7208309173584,-18.7208309173584,-18.7208309173584,-18.72083282470703,-18.72083282470703,-18.72083282470703,-18.72083282470703,-18.72083282470703,-18.72083282470703,-18.72083282470703,-18.72083282470703,-18.720836639404297,-18.720836639404297,-18.720836639404297,-18.720836639404297,-18.720836639404297,-18.720836639404297,-18.720836639404297,-18.720836639404297,-18.72083854675293,-18.72083854675293,-18.72083854675293,-18.72083854675293,-18.72083854675293,-18.72083854675293,-18.72083854675293,-18.72083854675293,-18.720842361450195,-18.720842361450195,-18.720842361450195,-18.720842361450195,-18.720842361450195,-18.720842361450195,-18.720842361450195,-18.720842361450195,-18.72084617614746,-18.72084617614746,-18.72084617614746,-18.72084617614746,-18.72084617614746,-18.72084617614746,-18.72084617614746,-18.72084617614746,-18.720848083496094,-18.720848083496094,-18.720848083496094,-18.720848083496094,-18.720848083496094,-18.720848083496094,-18.720848083496094,-18.720848083496094,-18.72085189819336,-18.72085189819336,-18.72085189819336,-18.72085189819336,-18.72085189819336,-18.72085189819336,-18.72085189819336,-18.72085189819336,-18.720853805541992,-18.720853805541992,-18.720853805541992,-18.720853805541992,-18.720853805541992,-18.720853805541992,-18.720853805541992,-18.720853805541992,-18.720857620239258,-18.720857620239258,-18.720857620239258,-18.720857620239258,-18.720857620239258,-18.720857620239258,-18.720857620239258,-18.720857620239258,-18.720861434936523,-18.720861434936523,-18.720861434936523,-18.720861434936523,-18.720861434936523,-18.720861434936523,-18.720861434936523,-18.720861434936523,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156,-18.720863342285156],"y":[-5.478541374206543,-5.478541374206543,-5.478541851043701,-5.478541851043701,-5.4785475730896,-5.4785475730896,-5.4785475730896,-5.4785475730896,-5.4785475730896,-5.4785475730896,-5.4785475730896,-5.4785475730896,-5.4785590171813965,-5.4785590171813965,-5.4785590171813965,-5.4785590171813965,-5.4785590171813965,-5.4785590171813965,-5.478559494018555,-5.478559494018555,-5.478570461273193,-5.478570461273193,-5.478570461273193,-5.478570461273193,-5.478570461273193,-5.478570461273193,-5.478570938110352,-5.478570938110352,-5.478579521179199,-5.478579521179199,-5.478579521179199,-5.478579521179199,-5.478579521179199,-5.478579521179199,-5.478579521179199,-5.478579521179199,-5.478585720062256,-5.478585720062256,-5.478585720062256,-5.478585720062256,-5.478585720062256,-5.478585720062256,-5.478586196899414,-5.478586196899414,-5.478589057922363,-5.478589057922363,-5.478589057922363,-5.478589057922363,-5.478589057922363,-5.478589057922363,-5.478589057922363,-5.478589057922363,-5.47859001159668,-5.47859001159668,-5.47859001159668,-5.47859001159668,-5.47859001159668,-5.47859001159668,-5.47859001159668,-5.47859001159668,-5.478588104248047,-5.478588104248047,-5.478588104248047,-5.478588104248047,-5.478588104248047,-5.478588104248047,-5.478588104248047,-5.478588104248047,-5.478584289550781,-5.478584289550781,-5.478584289550781,-5.478584289550781,-5.478584289550781,-5.478584289550781,-5.478584289550781,-5.478584289550781,-5.478579521179199,-5.478579521179199,-5.478579521179199,-5.478579521179199,-5.478579521179199,-5.478579521179199,-5.478579521179199,-5.478579521179199,-5.478574752807617,-5.478574752807617,-5.478574752807617,-5.478574752807617,-5.478574752807617,-5.478574752807617,-5.478574752807617,-5.478574752807617,-5.478569030761719,-5.478569030761719,-5.478569030761719,-5.478569030761719,-5.478569030761719,-5.478569030761719,-5.478569030761719,-5.478569030761719,-5.4785637855529785,-5.4785637855529785,-5.4785637855529785,-5.4785637855529785,-5.4785637855529785,-5.4785637855529785,-5.4785637855529785,-5.4785637855529785,-5.4785590171813965,-5.4785590171813965,-5.4785590171813965,-5.4785590171813965,-5.4785590171813965,-5.4785590171813965,-5.4785590171813965,-5.4785590171813965,-5.478554725646973,-5.478554725646973,-5.478554725646973,-5.478554725646973,-5.478554725646973,-5.478554725646973,-5.478554725646973,-5.478554725646973,-5.478549957275391,-5.478549957275391,-5.478549957275391,-5.478549957275391,-5.478549957275391,-5.478549957275391,-5.478549957275391,-5.478549957275391,-5.478545665740967,-5.478545665740967,-5.478545665740967,-5.478545665740967,-5.478545665740967,-5.478545665740967,-5.478545665740967,-5.478545665740967,-5.478541851043701,-5.478541851043701,-5.478541851043701,-5.478541851043701,-5.478541851043701,-5.478541851043701,-5.478541851043701,-5.478541851043701,-5.478538513183594,-5.478538513183594,-5.478538513183594,-5.478538513183594,-5.478538513183594,-5.478538513183594,-5.478538513183594,-5.478538513183594,-5.478536128997803,-5.478536128997803,-5.478536128997803,-5.478536128997803,-5.478536128997803,-5.478536128997803,-5.478536128997803,-5.478536128997803,-5.478534698486328,-5.478534698486328,-5.478534698486328,-5.478534698486328,-5.478534698486328,-5.478534698486328,-5.478534698486328,-5.478534698486328,-5.4785332679748535,-5.4785332679748535,-5.4785332679748535,-5.4785332679748535,-5.4785332679748535,-5.4785332679748535,-5.4785332679748535,-5.4785332679748535,-5.4785332679748535,-5.4785332679748535,-5.4785332679748535,-5.4785332679748535,-5.4785332679748535,-5.4785332679748535,-5.4785332679748535,-5.4785332679748535,-5.478534698486328,-5.478534698486328,-5.478534698486328,-5.478534698486328,-5.478534698486328,-5.478534698486328,-5.478534698486328,-5.478534698486328,-5.4785380363464355,-5.4785380363464355,-5.4785380363464355,-5.4785380363464355,-5.4785380363464355,-5.4785380363464355,-5.4785380363464355,-5.4785380363464355,-5.478540897369385,-5.478540897369385,-5.478540897369385,-5.478540897369385,-5.478540897369385,-5.478540897369385,-5.478540897369385,-5.478540897369385,-5.478545665740967,-5.478545665740967,-5.478545665740967,-5.478545665740967,-5.478545665740967,-5.478545665740967,-5.478545665740967,-5.478545665740967,-5.478548526763916,-5.478548526763916,-5.478548526763916,-5.478548526763916,-5.478548526763916,-5.478548526763916,-5.478548526763916,-5.478548526763916,-5.478551387786865,-5.478551387786865,-5.478551387786865,-5.478551387786865,-5.478551387786865,-5.478551387786865,-5.478551387786865,-5.478551387786865,-5.478553295135498,-5.478553295135498,-5.478553295135498,-5.478553295135498,-5.478553295135498,-5.478553295135498,-5.478553295135498,-5.478553295135498,-5.478554725646973,-5.478554725646973,-5.478554725646973,-5.478554725646973,-5.478554725646973,-5.478554725646973],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 2","showlegend":false,"x":[-16.706689834594727],"y":[-3.2457008361816406],"type":"scatter"},{"marker":{"color":"#AB63FA","size":3},"mode":"markers","name":"cluster 3","x":[-20.59412956237793,-20.59412956237793,-20.594131469726562,-20.594131469726562,-20.594131469726562,-20.594131469726562,-20.594131469726562,-20.594131469726562,-20.594131469726562,-20.594131469726562,-20.594133377075195,-20.594133377075195,-20.594133377075195,-20.594133377075195,-20.594133377075195,-20.594133377075195,-20.594133377075195,-20.594133377075195,-20.594141006469727,-20.594141006469727,-20.594141006469727,-20.594141006469727,-20.594141006469727,-20.594141006469727,-20.594141006469727,-20.594141006469727,-20.594148635864258,-20.594148635864258,-20.594148635864258,-20.594148635864258,-20.594148635864258,-20.594148635864258,-20.594148635864258,-20.594148635864258,-20.594158172607422,-20.594158172607422,-20.594158172607422,-20.594158172607422,-20.594158172607422,-20.594158172607422,-20.594158172607422,-20.594158172607422,-20.59416961669922,-20.59416961669922,-20.59416961669922,-20.59416961669922,-20.59416961669922,-20.59416961669922,-20.59416961669922,-20.59416961669922,-20.594181060791016,-20.594181060791016,-20.594181060791016,-20.594181060791016,-20.594181060791016,-20.594181060791016,-20.594181060791016,-20.594181060791016,-20.594192504882812,-20.594192504882812,-20.594192504882812,-20.594192504882812,-20.594192504882812,-20.594192504882812,-20.594192504882812,-20.594192504882812,-20.594202041625977,-20.594202041625977,-20.594202041625977,-20.594202041625977,-20.594202041625977,-20.594202041625977,-20.594202041625977,-20.594202041625977,-20.594213485717773,-20.594213485717773,-20.594213485717773,-20.594213485717773,-20.594213485717773,-20.594213485717773,-20.594213485717773,-20.594213485717773,-20.594223022460938,-20.594223022460938,-20.594223022460938,-20.594223022460938,-20.594223022460938,-20.594223022460938,-20.594223022460938,-20.594223022460938,-20.594228744506836,-20.594228744506836,-20.594228744506836,-20.594228744506836,-20.594228744506836,-20.594228744506836,-20.594228744506836,-20.594228744506836,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.5942325592041,-20.59423065185547,-20.59423065185547,-20.59423065185547,-20.59423065185547,-20.59423065185547,-20.59423065185547,-20.59423065185547,-20.59423065185547,-20.594226837158203,-20.594226837158203,-20.594226837158203,-20.594226837158203,-20.594226837158203,-20.594226837158203,-20.594226837158203,-20.594226837158203,-20.594221115112305,-20.594221115112305,-20.594221115112305,-20.594221115112305,-20.594221115112305,-20.594221115112305,-20.594221115112305,-20.594221115112305,-20.594215393066406,-20.594215393066406,-20.594215393066406,-20.594215393066406,-20.594215393066406,-20.594215393066406,-20.594215393066406,-20.594215393066406,-20.594209671020508,-20.594209671020508,-20.594209671020508,-20.594209671020508,-20.594209671020508,-20.594209671020508,-20.594209671020508,-20.594209671020508,-20.594202041625977,-20.594202041625977,-20.594202041625977,-20.594202041625977,-20.594202041625977,-20.594202041625977,-20.594202041625977,-20.594202041625977,-20.594196319580078,-20.594196319580078,-20.594196319580078,-20.594196319580078,-20.594196319580078,-20.594196319580078,-20.594196319580078,-20.594196319580078,-20.59419059753418,-20.59419059753418,-20.59419059753418,-20.59419059753418,-20.59419059753418,-20.59419059753418,-20.594192504882812,-20.594192504882812,-20.59418487548828,-20.59418487548828,-20.59418487548828,-20.59418487548828,-20.59418487548828,-20.59418487548828,-20.594186782836914,-20.594186782836914,-20.594179153442383,-20.594179153442383,-20.594179153442383,-20.594179153442383,-20.594179153442383,-20.594179153442383,-20.594179153442383,-20.594179153442383,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.594173431396484,-20.594173431396484,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.594173431396484,-20.594173431396484,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.594173431396484,-20.594173431396484,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.594173431396484,-20.594173431396484,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.594173431396484,-20.594173431396484,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.59417152404785,-20.594173431396484,-20.594173431396484],"y":[9.100281715393066,9.100281715393066,9.1002779006958,9.1002779006958,9.1002779006958,9.1002779006958,9.1002779006958,9.1002779006958,9.1002779006958,9.1002779006958,9.100261688232422,9.100261688232422,9.100261688232422,9.100261688232422,9.100261688232422,9.100261688232422,9.100261688232422,9.100261688232422,9.100247383117676,9.100247383117676,9.100247383117676,9.100247383117676,9.100247383117676,9.100247383117676,9.100247383117676,9.100247383117676,9.100234985351562,9.100234985351562,9.100234985351562,9.100234985351562,9.100234985351562,9.100234985351562,9.100234985351562,9.100234985351562,9.100223541259766,9.100223541259766,9.100223541259766,9.100223541259766,9.100223541259766,9.100223541259766,9.100223541259766,9.100223541259766,9.100217819213867,9.100217819213867,9.100217819213867,9.100217819213867,9.100217819213867,9.100217819213867,9.100217819213867,9.100217819213867,9.100214958190918,9.100214958190918,9.100214958190918,9.100214958190918,9.100214958190918,9.100214958190918,9.100214958190918,9.100214958190918,9.100215911865234,9.100215911865234,9.100215911865234,9.100215911865234,9.100215911865234,9.100215911865234,9.100215911865234,9.100215911865234,9.1002197265625,9.1002197265625,9.1002197265625,9.1002197265625,9.1002197265625,9.1002197265625,9.1002197265625,9.1002197265625,9.100225448608398,9.100225448608398,9.100225448608398,9.100225448608398,9.100225448608398,9.100225448608398,9.100225448608398,9.100225448608398,9.100231170654297,9.100231170654297,9.100231170654297,9.100231170654297,9.100231170654297,9.100231170654297,9.100231170654297,9.100231170654297,9.100236892700195,9.100236892700195,9.100236892700195,9.100236892700195,9.100236892700195,9.100236892700195,9.100236892700195,9.100236892700195,9.100242614746094,9.100242614746094,9.100242614746094,9.100242614746094,9.100242614746094,9.100242614746094,9.100242614746094,9.100242614746094,9.100250244140625,9.100250244140625,9.100250244140625,9.100250244140625,9.100250244140625,9.100250244140625,9.100250244140625,9.100250244140625,9.10025405883789,9.10025405883789,9.10025405883789,9.10025405883789,9.10025405883789,9.10025405883789,9.10025405883789,9.10025405883789,9.100260734558105,9.100260734558105,9.100260734558105,9.100260734558105,9.100260734558105,9.100260734558105,9.100260734558105,9.100260734558105,9.100265502929688,9.100265502929688,9.100265502929688,9.100265502929688,9.100265502929688,9.100265502929688,9.100265502929688,9.100265502929688,9.100269317626953,9.100269317626953,9.100269317626953,9.100269317626953,9.100269317626953,9.100269317626953,9.100269317626953,9.100269317626953,9.100273132324219,9.100273132324219,9.100273132324219,9.100273132324219,9.100273132324219,9.100273132324219,9.100273132324219,9.100273132324219,9.100275993347168,9.100275993347168,9.100275993347168,9.100275993347168,9.100275993347168,9.100275993347168,9.100275993347168,9.100275993347168,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100276947021484,9.100275993347168,9.100275993347168,9.100275993347168,9.100275993347168,9.100275993347168,9.100275993347168,9.100275993347168,9.100275993347168,9.100274085998535,9.100274085998535,9.100274085998535,9.100274085998535,9.100274085998535,9.100274085998535,9.100274085998535,9.100274085998535,9.100271224975586,9.100271224975586,9.100271224975586,9.100271224975586,9.100271224975586,9.100271224975586,9.100271224975586,9.100271224975586,9.100268363952637,9.100268363952637,9.100268363952637,9.100268363952637,9.100268363952637,9.100268363952637,9.100268363952637,9.100268363952637,9.100265502929688,9.100265502929688,9.100265502929688,9.100265502929688,9.100265502929688,9.100265502929688,9.100265502929688,9.100265502929688,9.100261688232422,9.100261688232422,9.100261688232422,9.100261688232422,9.100261688232422,9.100261688232422,9.100261688232422,9.100261688232422,9.100258827209473,9.100258827209473,9.100258827209473,9.100258827209473,9.100258827209473,9.100258827209473,9.100258827209473,9.100258827209473,9.100258827209473,9.100258827209473,9.100258827209473,9.100258827209473,9.100258827209473,9.100258827209473,9.100258827209473,9.100258827209473],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 3","showlegend":false,"x":[-18.503978729248047],"y":[11.081546783447266],"type":"scatter"},{"marker":{"color":"#FFA15A","size":3},"mode":"markers","name":"cluster 4","x":[-9.63476848602295,-9.63476848602295,-9.63476848602295,-9.63476848602295,-9.63476848602295,-9.63476848602295,-9.63476848602295,-9.63476848602295,-9.634774208068848,-9.634774208068848,-9.634774208068848,-9.634774208068848,-9.634774208068848,-9.634774208068848,-9.634774208068848,-9.634774208068848,-9.634780883789062,-9.634780883789062,-9.634780883789062,-9.634780883789062,-9.634780883789062,-9.634780883789062,-9.634780883789062,-9.634780883789062,-9.634788513183594,-9.634788513183594,-9.634788513183594,-9.634788513183594,-9.634788513183594,-9.634788513183594,-9.634788513183594,-9.634788513183594,-9.634797096252441,-9.634797096252441,-9.634797096252441,-9.634797096252441,-9.634797096252441,-9.634797096252441,-9.634798049926758,-9.634798049926758,-9.634804725646973,-9.634804725646973,-9.634804725646973,-9.634804725646973,-9.634804725646973,-9.634804725646973,-9.634805679321289,-9.634805679321289,-9.634811401367188,-9.634811401367188,-9.634811401367188,-9.634811401367188,-9.634811401367188,-9.634811401367188,-9.634811401367188,-9.634811401367188,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634819030761719,-9.634819030761719,-9.634825706481934,-9.634825706481934,-9.634825706481934,-9.634825706481934,-9.634825706481934,-9.634825706481934,-9.634825706481934,-9.634825706481934,-9.634831428527832,-9.634831428527832,-9.634831428527832,-9.634831428527832,-9.634831428527832,-9.634831428527832,-9.634831428527832,-9.634831428527832,-9.63483715057373,-9.63483715057373,-9.63483715057373,-9.63483715057373,-9.63483715057373,-9.63483715057373,-9.634836196899414,-9.634836196899414,-9.634840965270996,-9.634840965270996,-9.634840965270996,-9.634840965270996,-9.634840965270996,-9.634840965270996,-9.634840965270996,-9.634840965270996,-9.634844779968262,-9.634844779968262,-9.634844779968262,-9.634844779968262,-9.634844779968262,-9.634844779968262,-9.634843826293945,-9.634843826293945,-9.634845733642578,-9.634845733642578,-9.634845733642578,-9.634845733642578,-9.634845733642578,-9.634845733642578,-9.634844779968262,-9.634844779968262,-9.634845733642578,-9.634845733642578,-9.634845733642578,-9.634845733642578,-9.634845733642578,-9.634845733642578,-9.634844779968262,-9.634844779968262,-9.634844779968262,-9.634844779968262,-9.634844779968262,-9.634844779968262,-9.634844779968262,-9.634844779968262,-9.634843826293945,-9.634843826293945,-9.634842872619629,-9.634842872619629,-9.634842872619629,-9.634842872619629,-9.634842872619629,-9.634842872619629,-9.634841918945312,-9.634841918945312,-9.63484001159668,-9.63484001159668,-9.63484001159668,-9.63484001159668,-9.63484001159668,-9.63484001159668,-9.634839057922363,-9.634839057922363,-9.63483715057373,-9.63483715057373,-9.63483715057373,-9.63483715057373,-9.63483715057373,-9.63483715057373,-9.634836196899414,-9.634836196899414,-9.634833335876465,-9.634833335876465,-9.634833335876465,-9.634833335876465,-9.634833335876465,-9.634833335876465,-9.634833335876465,-9.634833335876465,-9.634830474853516,-9.634830474853516,-9.634830474853516,-9.634830474853516,-9.634830474853516,-9.634830474853516,-9.6348295211792,-9.6348295211792,-9.634827613830566,-9.634827613830566,-9.634827613830566,-9.634827613830566,-9.634827613830566,-9.634827613830566,-9.63482666015625,-9.63482666015625,-9.634824752807617,-9.634824752807617,-9.634824752807617,-9.634824752807617,-9.634824752807617,-9.634824752807617,-9.6348237991333,-9.6348237991333,-9.634822845458984,-9.634822845458984,-9.634822845458984,-9.634822845458984,-9.634822845458984,-9.634822845458984,-9.634821891784668,-9.634821891784668,-9.634821891784668,-9.634821891784668,-9.634821891784668,-9.634821891784668,-9.634821891784668,-9.634821891784668,-9.634820938110352,-9.634820938110352,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402,-9.634818077087402],"y":[24.508512496948242,24.508512496948242,24.508512496948242,24.508512496948242,24.508512496948242,24.508512496948242,24.50851058959961,24.50851058959961,24.508502960205078,24.508502960205078,24.508502960205078,24.508502960205078,24.508502960205078,24.508502960205078,24.508501052856445,24.508501052856445,24.508495330810547,24.508495330810547,24.508495330810547,24.508495330810547,24.508495330810547,24.508495330810547,24.508493423461914,24.508493423461914,24.50848960876465,24.50848960876465,24.50848960876465,24.50848960876465,24.50848960876465,24.50848960876465,24.508485794067383,24.508485794067383,24.508480072021484,24.508480072021484,24.508480072021484,24.508480072021484,24.508480072021484,24.508480072021484,24.508480072021484,24.508480072021484,24.508474349975586,24.508474349975586,24.508474349975586,24.508474349975586,24.508474349975586,24.508474349975586,24.508474349975586,24.508474349975586,24.508464813232422,24.508464813232422,24.508464813232422,24.508464813232422,24.508464813232422,24.508464813232422,24.508464813232422,24.508464813232422,24.508455276489258,24.508455276489258,24.508455276489258,24.508455276489258,24.508455276489258,24.508455276489258,24.508455276489258,24.508455276489258,24.50844955444336,24.50844955444336,24.50844955444336,24.50844955444336,24.50844955444336,24.50844955444336,24.50844955444336,24.50844955444336,24.508440017700195,24.508440017700195,24.508440017700195,24.508440017700195,24.508440017700195,24.508440017700195,24.508440017700195,24.508440017700195,24.508434295654297,24.508434295654297,24.508434295654297,24.508434295654297,24.508434295654297,24.508434295654297,24.508434295654297,24.508434295654297,24.508424758911133,24.508424758911133,24.508424758911133,24.508424758911133,24.508424758911133,24.508424758911133,24.508424758911133,24.508424758911133,24.50841522216797,24.50841522216797,24.50841522216797,24.50841522216797,24.50841522216797,24.50841522216797,24.50841522216797,24.50841522216797,24.50840950012207,24.50840950012207,24.50840950012207,24.50840950012207,24.50840950012207,24.50840950012207,24.50840950012207,24.50840950012207,24.508405685424805,24.508405685424805,24.508405685424805,24.508405685424805,24.508405685424805,24.508405685424805,24.508405685424805,24.508405685424805,24.508403778076172,24.508403778076172,24.508403778076172,24.508403778076172,24.508403778076172,24.508403778076172,24.508403778076172,24.508403778076172,24.508403778076172,24.508403778076172,24.508403778076172,24.508403778076172,24.508403778076172,24.508403778076172,24.508403778076172,24.508403778076172,24.508405685424805,24.508405685424805,24.508405685424805,24.508405685424805,24.508405685424805,24.508405685424805,24.508405685424805,24.508405685424805,24.50840950012207,24.50840950012207,24.50840950012207,24.50840950012207,24.50840950012207,24.50840950012207,24.50840950012207,24.50840950012207,24.50841522216797,24.50841522216797,24.50841522216797,24.50841522216797,24.50841522216797,24.50841522216797,24.50841522216797,24.50841522216797,24.508420944213867,24.508420944213867,24.508420944213867,24.508420944213867,24.508420944213867,24.508420944213867,24.508420944213867,24.508420944213867,24.508426666259766,24.508426666259766,24.508426666259766,24.508426666259766,24.508426666259766,24.508426666259766,24.508426666259766,24.508426666259766,24.508434295654297,24.508434295654297,24.508434295654297,24.508434295654297,24.508434295654297,24.508434295654297,24.508434295654297,24.508434295654297,24.508440017700195,24.508440017700195,24.508440017700195,24.508440017700195,24.508440017700195,24.508440017700195,24.508440017700195,24.508440017700195,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094,24.508445739746094],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 4","showlegend":false,"x":[-7.42786979675293],"y":[26.588783264160156],"type":"scatter"},{"marker":{"color":"#19D3F3","size":3},"mode":"markers","name":"cluster 5","x":[24.874143600463867,24.874143600463867,24.874143600463867,24.874143600463867,24.874143600463867,24.874143600463867,24.874134063720703,24.874134063720703,24.874134063720703,24.874134063720703,24.874134063720703,24.874134063720703,24.874134063720703,24.874134063720703,24.874122619628906,24.874122619628906,24.874122619628906,24.874122619628906,24.874122619628906,24.874122619628906,24.874122619628906,24.874122619628906,24.874109268188477,24.874109268188477,24.874109268188477,24.874109268188477,24.874109268188477,24.874109268188477,24.874109268188477,24.874109268188477,24.87409782409668,24.87409782409668,24.87409782409668,24.87409782409668,24.87409782409668,24.87409782409668,24.87409782409668,24.87409782409668,24.874088287353516,24.874088287353516,24.874088287353516,24.874088287353516,24.874088287353516,24.874088287353516,24.874088287353516,24.874088287353516,24.874080657958984,24.874080657958984,24.874080657958984,24.874080657958984,24.874080657958984,24.874080657958984,24.874080657958984,24.874080657958984,24.874074935913086,24.874074935913086,24.874074935913086,24.874074935913086,24.874074935913086,24.874074935913086,24.874074935913086,24.874074935913086,24.87407112121582,24.87407112121582,24.87407112121582,24.87407112121582,24.87407112121582,24.87407112121582,24.87407112121582,24.87407112121582,24.874065399169922,24.874065399169922,24.874065399169922,24.874065399169922,24.874065399169922,24.874065399169922,24.874065399169922,24.874065399169922,24.87406349182129,24.87406349182129,24.87406349182129,24.87406349182129,24.87406349182129,24.87406349182129,24.87406349182129,24.87406349182129,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.874059677124023,24.87406349182129,24.87406349182129,24.87406349182129,24.87406349182129,24.87406349182129,24.87406349182129,24.87406349182129,24.87406349182129,24.874065399169922,24.874065399169922,24.874065399169922,24.874065399169922,24.874065399169922,24.874065399169922,24.874065399169922,24.874065399169922,24.874069213867188,24.874069213867188,24.874069213867188,24.874069213867188,24.874069213867188,24.874069213867188,24.874069213867188,24.874069213867188,24.874073028564453,24.874073028564453,24.874073028564453,24.874073028564453,24.874073028564453,24.874073028564453,24.874073028564453,24.874073028564453,24.87407875061035,24.87407875061035,24.87407875061035,24.87407875061035,24.87407875061035,24.87407875061035,24.87407875061035,24.87407875061035,24.874086380004883,24.874086380004883,24.874086380004883,24.874086380004883,24.874086380004883,24.874086380004883,24.874086380004883,24.874086380004883,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078,24.87409210205078],"y":[3.7232511043548584,3.7232511043548584,3.7232511043548584,3.7232511043548584,3.7232511043548584,3.7232511043548584,3.7232749462127686,3.7232749462127686,3.7232749462127686,3.7232749462127686,3.7232749462127686,3.7232749462127686,3.7232749462127686,3.7232749462127686,3.7233023643493652,3.7233023643493652,3.7233023643493652,3.7233023643493652,3.7233023643493652,3.7233023643493652,3.7233023643493652,3.7233023643493652,3.7233238220214844,3.7233238220214844,3.7233238220214844,3.7233238220214844,3.7233238220214844,3.7233238220214844,3.7233238220214844,3.7233238220214844,3.723339557647705,3.723339557647705,3.723339557647705,3.723339557647705,3.723339557647705,3.723339557647705,3.723339557647705,3.723339557647705,3.7233498096466064,3.7233498096466064,3.7233498096466064,3.7233498096466064,3.7233498096466064,3.7233498096466064,3.7233498096466064,3.7233498096466064,3.723355531692505,3.723355531692505,3.723355531692505,3.723355531692505,3.723355531692505,3.723355531692505,3.723355531692505,3.723355531692505,3.723357915878296,3.723357915878296,3.723357915878296,3.723357915878296,3.723357915878296,3.723357915878296,3.723357915878296,3.723357915878296,3.7233572006225586,3.7233572006225586,3.7233572006225586,3.7233572006225586,3.7233572006225586,3.7233572006225586,3.7233572006225586,3.7233572006225586,3.723353385925293,3.723353385925293,3.723353385925293,3.723353385925293,3.723353385925293,3.723353385925293,3.723353624343872,3.723353624343872,3.7233471870422363,3.7233471870422363,3.7233471870422363,3.7233471870422363,3.7233471870422363,3.7233471870422363,3.7233476638793945,3.7233476638793945,3.723339080810547,3.723339080810547,3.723339080810547,3.723339080810547,3.723339080810547,3.723339080810547,3.723339557647705,3.723339557647705,3.7233307361602783,3.7233307361602783,3.7233307361602783,3.7233307361602783,3.7233307361602783,3.7233307361602783,3.7233312129974365,3.7233312129974365,3.723322629928589,3.723322629928589,3.723322629928589,3.723322629928589,3.723322629928589,3.723322629928589,3.723323106765747,3.723323106765747,3.7233147621154785,3.7233147621154785,3.7233147621154785,3.7233147621154785,3.7233147621154785,3.7233147621154785,3.7233150005340576,3.7233150005340576,3.723306655883789,3.723306655883789,3.723306655883789,3.723306655883789,3.723306655883789,3.723306655883789,3.7233071327209473,3.7233071327209473,3.723299741744995,3.723299741744995,3.723299741744995,3.723299741744995,3.723299741744995,3.723299741744995,3.723299741744995,3.723299741744995,3.7232935428619385,3.7232935428619385,3.7232935428619385,3.7232935428619385,3.7232935428619385,3.7232935428619385,3.7232935428619385,3.7232935428619385,3.723287582397461,3.723287582397461,3.723287582397461,3.723287582397461,3.723287582397461,3.723287582397461,3.723287582397461,3.723287582397461,3.723282814025879,3.723282814025879,3.723282814025879,3.723282814025879,3.723282814025879,3.723282814025879,3.723282814025879,3.723282814025879,3.7232799530029297,3.7232799530029297,3.7232799530029297,3.7232799530029297,3.7232799530029297,3.7232799530029297,3.7232799530029297,3.7232799530029297,3.7232775688171387,3.7232775688171387,3.7232775688171387,3.7232775688171387,3.7232775688171387,3.7232775688171387,3.7232775688171387,3.7232775688171387,3.7232768535614014,3.7232768535614014,3.7232768535614014,3.7232768535614014,3.7232768535614014,3.7232768535614014,3.7232768535614014,3.7232768535614014,3.7232775688171387,3.7232775688171387,3.7232775688171387,3.7232775688171387,3.7232775688171387,3.7232775688171387,3.7232775688171387,3.7232775688171387,3.7232799530029297,3.7232799530029297,3.7232799530029297,3.7232799530029297,3.7232799530029297,3.7232799530029297,3.7232799530029297,3.7232799530029297,3.7232837677001953,3.7232837677001953,3.7232837677001953,3.7232837677001953,3.7232837677001953,3.7232837677001953,3.7232837677001953,3.7232837677001953,3.723287582397461,3.723287582397461,3.723287582397461,3.723287582397461,3.723287582397461,3.723287582397461,3.723287582397461,3.723287582397461,3.723292112350464,3.723292112350464,3.723292112350464,3.723292112350464,3.723292112350464,3.723292112350464,3.723292112350464,3.723292112350464,3.723296642303467,3.723296642303467,3.723296642303467,3.723296642303467,3.723296642303467,3.723296642303467,3.723296642303467,3.723296642303467,3.7233011722564697,3.7233011722564697,3.7233011722564697,3.7233011722564697,3.7233011722564697,3.7233011722564697,3.7233011722564697,3.7233011722564697,3.7233059406280518,3.7233059406280518,3.7233059406280518,3.7233059406280518,3.7233059406280518,3.7233059406280518,3.7233059406280518,3.7233059406280518,3.72330904006958,3.72330904006958,3.72330904006958,3.72330904006958],"type":"scatter"},{"marker":{"color":"black","size":15,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"},{"marker":{"color":"red","size":7,"symbol":"x"},"mode":"markers","name":"centroid 5","showlegend":false,"x":[26.846019744873047],"y":[5.565464019775391],"type":"scatter"}],                        {"template":{"data":{"scatter":[{"marker":{"color":"#d92310"},"type":"scatter"}]},"layout":{"height":576,"paper_bgcolor":"#fcfcfc","plot_bgcolor":"#fcfcfc","width":1024}},"xaxis":{"zeroline":false},"yaxis":{"zeroline":false}},                        {"responsive": true}                    ).then(function(){
                            
var gd = document.getElementById('5c5d978c-ac2f-4917-97a3-f419c75301c0');
var x = new MutationObserver(function (mutations, observer) {{
        var display = window.getComputedStyle(gd).display;
        if (!display || display === 'none') {{
            console.log([gd, 'removed!']);
            Plotly.purge(gd);
            observer.disconnect();
        }}
}});

// Listen for the removal of the full notebook cells
var notebookContainer = gd.closest('#notebook-container');
if (notebookContainer) {{
    x.observe(notebookContainer, {childList: true});
}}

// Listen for the clearing of the current output cell
var outputEl = gd.closest('.output');
if (outputEl) {{
    x.observe(outputEl, {childList: true});
}}

                        })                };                });            </script>        </div>
</div>
</div>
<div id="f4d4a82d" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb77" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb77-1"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>timeit <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>n <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span> meanshift(data)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>700 ms ± 43.4 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)</code></pre>
</div>
</div>
<p>From 1.5 seconds to 0.5 seconds! A 3x speed increase — very nice!</p>
<p>Let’s move onto the GPU and now see what improvements we get.</p>
<div id="499f62cf" class="cell">
<div class="code-copy-outer-scaffold"><div class="sourceCode cell-code" id="cb79" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb79-1"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> meanshift(data):</span>
<span id="cb79-2">   X <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> data.clone().to(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">'cuda'</span>)</span>
<span id="cb79-3">   <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>): update(X)</span>
<span id="cb79-4">   <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> X.detach().cpu()</span>
<span id="cb79-5"></span>
<span id="cb79-6"><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span>timeit <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span>n <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span> meanshift(data)</span></code></pre></div></div>
<div class="cell-output cell-output-stdout">
<pre><code>263 ms ± 27.4 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)</code></pre>
</div>
</div>
<p>0.5s to 0.25s — a 2x speed increase!</p>
</section>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>Meanshift clustering simply involves moving points, by taking into account surrounding points, iteratively until they converge.</p>
<p>If you have any comments, questions, suggestions, feedback, criticisms, or corrections, please do post them down in the comment section below!</p>


</section>

<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Creating Models</category>
  <category>fastai</category>
  <guid>https://forbo7.github.io/forblog/posts/17_meanshift_clustering.html</guid>
  <pubDate>Wed, 21 Jun 2023 00:00:00 GMT</pubDate>
  <media:content url="https://forbo7.github.io/forblog/images/17_meanshift_clustering/thumbnail.png" medium="image" type="image/png" height="81" width="144"/>
</item>
<item>
  <title>Intuitively Approaching Einstein Summation Notation</title>
  <dc:creator>Salman Naqvi</dc:creator>
  <link>https://forbo7.github.io/forblog/posts/16_einstein_summation_notation.html</link>
  <description><![CDATA[ 




<div class="callout callout-style-simple callout-warning">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>This post covers einstein summation notation syntax in terms of programming languages.</p>
</div>
</div>
</div>
<p><img src="https://forbo7.github.io/forblog/images/16_einstein_summation/thumbnail.png" class="img-fluid"></p>
<p>Einstein summation notation (or einsum notation for short) is a handy way to write various matrix operations in a succinct, universal manner. With it, you can probably forget all the various symbols and operators there are and stick to one common syntax, that once understood, can be more intuitive.</p>
<p>For example, matrix multiplication can be written as <code>ik, kj -&gt; ij</code> and a transpose of a matrix can be written as <code>ij -&gt; ji</code>.</p>
<p>Let’s figure this out.</p>
<section id="general-rules" class="level2">
<h2 class="anchored" data-anchor-id="general-rules">General Rules</h2>
<p>The following are two general rules one can use to quickly write einsum notation.</p>
<blockquote class="blockquote">
<p>Repeating letters between input arrays means that values along those axes will be multiplied together.</p>
</blockquote>
<blockquote class="blockquote">
<p>Omitting a letter from the output means that values along that axis will be summed.</p>
</blockquote>
<p>However, I don’t find these rules intuitive, even a little confusing. Why?</p>
<p>Matrices have the order of row by column. A 2x3 matrix has 2 rows and 3 columns. When we perform matrix multiplication, we take the dot product of each row in the first matrix with each column in the second matrix.</p>
<p>However, when the einsum rules above — specifically the first rule — are used to denote matrix multiplication (<img src="https://latex.codecogs.com/png.latex?ik,%20kj%20%5Crightarrow%20ij">, as depicted below), the order of a matrix appears to change.</p>
<p><img src="https://forbo7.github.io/forblog/images/16_einstein_summation/1.png" class="img-fluid"></p>
<p>In order for the einsum rules and the definition of matrix multiplcation above to stay consistent, <img src="https://latex.codecogs.com/png.latex?k"> now denotes the rows in the first matrix and columns in the second matrix, thereby changing the order of a matrix to column by row.</p>
<p>But even if we let <img src="https://latex.codecogs.com/png.latex?k"> denote the columns in the first matrix, we end up doing dot products with each <em>column</em> in the first matrix and with each <em>row</em> in the second matrix.</p>
<p>Not intuitive.</p>
</section>
<section id="a-more-intuitive-way" class="level2 page-columns page-full">
<h2 class="anchored" data-anchor-id="a-more-intuitive-way">A More Intuitive Way</h2>
<p>The key to understanding einsum notation is to not think of axes, but of iterators. For example, <img src="https://latex.codecogs.com/png.latex?i"> is an iterator that returns the rows of a matrix. <img src="https://latex.codecogs.com/png.latex?j"> is an iterator that returns the columns of a matrix.</p>
<p>Let’s begin with a relatively more simple example: the hadamard product (also known as the elementwise product or elementwise multiplication.)</p>
<section id="hadamard-product" class="level3 page-columns page-full">
<h3 class="anchored" data-anchor-id="hadamard-product">Hadamard Product</h3>
<p>We have the following two matrices.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AA%0A=%0A%5Cbegin%7Bbmatrix%7D%0A1%20&amp;%202%20&amp;%203%20%5C%5C%0A4%20&amp;%205%20&amp;%206%20%5C%5C%0A7%20&amp;%208%20&amp;%209%0A%5Cend%7Bbmatrix%7D,%0AB%0A=%0A%5Cbegin%7Bbmatrix%7D%0A9%20&amp;%208%20&amp;%207%20%5C%5C%0A6%20&amp;%205%20&amp;%204%20%5C%5C%0A3%20&amp;%202%20&amp;%201%0A%5Cend%7Bbmatrix%7D%0A"></p>
<p>To access the element 8 in matrix <img src="https://latex.codecogs.com/png.latex?A">, we need to return the second row and first column<sup>1</sup>. This can be denoted as <img src="https://latex.codecogs.com/png.latex?a_%7B21%7D">. The first digit in the subscript refers to the row and the second refers to the column. We can refer to any entry generally as <img src="https://latex.codecogs.com/png.latex?a_%7Bij%7D">.</p>
<div class="no-row-height column-margin column-container"><div id="fn1"><p><sup>1</sup>&nbsp;This assumes the matrix is zero indexed. This means <img src="https://latex.codecogs.com/png.latex?%5Cbegin%7Bbmatrix%7D%201%20&amp;%202%20&amp;%203%20%5Cend%7Bbmatrix%7D"> is the zeroth row of <img src="https://latex.codecogs.com/png.latex?A">.</p></div></div><p>Taking the hadamard product looks like this.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Bbmatrix%7D%0A1%20&amp;%202%20&amp;%203%20%5C%5C%0A4%20&amp;%205%20&amp;%206%20%5C%5C%0A7%20&amp;%208%20&amp;%209%0A%5Cend%7Bbmatrix%7D%0A%5Codot%0A%5Cbegin%7Bbmatrix%7D%0A9%20&amp;%208%20&amp;%207%20%5C%5C%0A6%20&amp;%205%20&amp;%204%20%5C%5C%0A3%20&amp;%202%20&amp;%201%0A%5Cend%7Bbmatrix%7D%0A=%0A%5Cbegin%7Bbmatrix%7D%0A1%20%5Ccdot%209%20&amp;%202%20%5Ccdot%208%20&amp;%203%20%5Ccdot%207%20%5C%5C%0A4%20%5Ccdot%206%20&amp;%205%20%5Ccdot%205%20&amp;%206%20%5Ccdot%204%20%5C%5C%0A7%20%5Ccdot%203%20&amp;%208%20%5Ccdot%202%20&amp;%209%20%5Ccdot%201%0A%5Cend%7Bbmatrix%7D%0A=%0AC%0A"></p>
<div class="callout callout-style-simple callout-note no-icon callout-titled">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-1-contents" aria-controls="callout-1" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon no-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>An alternative way to look at it…
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-1" class="callout-1-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<div class="callout callout-style-simple callout-warning">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>Don’t dwell too much on this; it may help to refer back to this later to help understand the einsum notation below.</p>
</div>
</div>
</div>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Bbmatrix%7D%201%20&amp;%202%20&amp;%203%20%5C%5C%204%20&amp;%205%20&amp;%206%20%5C%5C%207%20&amp;%208%20&amp;%209%20%5Cend%7Bbmatrix%7D%20%5Codot%20%5Cbegin%7Bbmatrix%7D%209%20&amp;%208%20&amp;%207%20%5C%5C%206%20&amp;%205%20&amp;%204%20%5C%5C%203%20&amp;%202%20&amp;%201%20%5Cend%7Bbmatrix%7D%20=%20%5Cbegin%7Bbmatrix%7D%20a_%7B00%7Db_%7B00%7D%20&amp;%20a_%7B01%7Db_%7B01%7D%20&amp;%20a_%7B02%7Db_%7B02%7D%20%5C%5C%20a_%7B10%7Db_%7B10%7D%20&amp;%20a_%7B11%7Db_%7B11%7D%20&amp;%20a_%7B12%7Db_%7B12%7D%20%5C%5C%20a_%7B20%7Db_%7B20%7D%20&amp;%20a_%7B21%7Db_%7B21%7D%20&amp;%20a_%7B22%7Db_%7B22%7D%20%5C%5C%20%5Cend%7Bbmatrix%7D%20=%20C%0A"></p>
</div>
</div>
</div>
<p>In words, what’s happening is that we’re looping through all the rows of <img src="https://latex.codecogs.com/png.latex?A"> and <img src="https://latex.codecogs.com/png.latex?B">. For each row, we also loop through each column and multiply those columns together.</p>
<blockquote class="blockquote">
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7Bfor%20row%20in%20%7D%20A%20%5Ctext%7B%20and%20%7D%20B"></p>
<p>&nbsp;&nbsp;<img src="https://latex.codecogs.com/png.latex?%5Ctext%7Bfor%20col%20in%20%7D%20A%20%5Ctext%7B%20and%20%7D%20B"></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;<img src="https://latex.codecogs.com/png.latex?a_%7B%5Ctext%7Browcol%7D%7D%20%5Ccdot%20b_%7B%5Ctext%7Browcol%7D%7D%20=%20c_%7B%5Ctext%7Browcol%7D%7D"></p>
</blockquote>
<blockquote class="blockquote">
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7Bfor%20%7D%20i%20%5Ctext%7B%20in%20%7D%20A%20%5Ctext%7B%20and%20%7D%20B"></p>
<p>&nbsp;&nbsp;<img src="https://latex.codecogs.com/png.latex?%5Ctext%7Bfor%20%7D%20j%20%5Ctext%7B%20in%20%7D%20A%20%5Ctext%7B%20and%20%7D%20B"></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;<img src="https://latex.codecogs.com/png.latex?a_%7Bij%7D%20%5Ccdot%20b_%7Bij%7D%20=%20c_%7Bij%7D"></p>
</blockquote>
<p>Let’s focus on that last line above.</p>
<p><img src="https://latex.codecogs.com/png.latex?a_%7Bij%7D%20%5Ccdot%20b_%7Bij%7D%20=%20c_%7Bij%7D"></p>
<p>This line represents elementwise multiplication. For each row <img src="https://latex.codecogs.com/png.latex?i"> in <img src="https://latex.codecogs.com/png.latex?A"> and <img src="https://latex.codecogs.com/png.latex?B">, we iterate through each column <img src="https://latex.codecogs.com/png.latex?j"> in those rows, and take their product.</p>
<p>In einsum notation, we can more succinctly write this as <img src="https://latex.codecogs.com/png.latex?ij,%20ij%20%5Crightarrow%20ij">. This has 4 parts.</p>
<ol type="1">
<li><img src="https://latex.codecogs.com/png.latex?ij"> refers to the iterators working on the rows and columns of <img src="https://latex.codecogs.com/png.latex?A"> — <img src="https://latex.codecogs.com/png.latex?i"> works on the rows and <img src="https://latex.codecogs.com/png.latex?j"> works on the columns.</li>
<li><img src="https://latex.codecogs.com/png.latex?ij"> refers to the exact same iterators working on <img src="https://latex.codecogs.com/png.latex?B">.</li>
<li><img src="https://latex.codecogs.com/png.latex?%5Crightarrow"> tells us an output will be returned.</li>
<li><img src="https://latex.codecogs.com/png.latex?ij"> refers to the exact same iterators that will be responsble for making up the output matrix <img src="https://latex.codecogs.com/png.latex?C">. The location <img src="https://latex.codecogs.com/png.latex?ij"> says where the product of two elements will be located in <img src="https://latex.codecogs.com/png.latex?C">.</li>
</ol>
</section>
<section id="matrix-multiplication" class="level3">
<h3 class="anchored" data-anchor-id="matrix-multiplication">Matrix Multiplication</h3>
<p>Let’s cover matrix multiplication in the same manner as above.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0AA%0A=%0A%5Cbegin%7Bbmatrix%7D%0A1%20&amp;%202%20%5C%5C%0A3%20&amp;%204%0A%5Cend%7Bbmatrix%7D%0A,%0AB%0A=%0A%5Cbegin%7Bbmatrix%7D%0A5%20&amp;%206%20%5C%5C%0A7%20&amp;%208%0A%5Cend%7Bbmatrix%7D%0A"></p>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Bbmatrix%7D%0A1%20&amp;%202%20%5C%5C%0A3%20&amp;%204%0A%5Cend%7Bbmatrix%7D%0A%5Ccdot%0A%5Cbegin%7Bbmatrix%7D%0A5%20&amp;%206%20%5C%5C%0A7%20&amp;%208%0A%5Cend%7Bbmatrix%7D%0A=%0A%5Cbegin%7Bbmatrix%7D%0A(1%20%5Ccdot%205)%20+%20(2%20%5Ccdot%207)%20&amp;%20(1%20%5Ccdot%206)%20+%20(2%20%5Ccdot%208)%20%5C%5C%0A(3%20%5Ccdot%205)%20+%20(4%20%5Ccdot%207)%20&amp;%20(3%20%5Ccdot%206)%20+%20(4%20%5Ccdot%208)%0A%5Cend%7Bbmatrix%7D%0A=%0AC%0A"></p>
<!-- TODO: Might want to remove the example below or position it after the einsum notation for matrix multiplication. -->
<div class="callout callout-style-simple callout-note no-icon callout-titled">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-2-contents" aria-controls="callout-2" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon no-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>An alternative way to look at it…
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-2" class="callout-2-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<div class="callout callout-style-simple callout-warning">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>Don’t dwell too much on this; it may help to refer back to this later to help understand the einsum notation below.</p>
</div>
</div>
</div>
<p><img src="https://latex.codecogs.com/png.latex?%0A%5Cbegin%7Bbmatrix%7D%0A1%20&amp;%202%20%5C%5C%0A3%20&amp;%204%0A%5Cend%7Bbmatrix%7D%0A%5Ccdot%0A%5Cbegin%7Bbmatrix%7D%0A5%20&amp;%206%20%5C%5C%0A7%20&amp;%208%0A%5Cend%7Bbmatrix%7D%0A=%0A%5Cbegin%7Bbmatrix%7D%0A(a_%7B00%7Db_%7B00%7D%20+%20a_%7B01%7Db_%7B10%7D)%20&amp;%20(a_%7B00%7Db_%7B01%7D%20+%20a_%7B01%7Db_%7B11%7D)%20%5C%5C%0A(a_%7B10%7Db_%7B00%7D%20+%20a_%7B11%7Db_%7B10%7D)%20&amp;%20(a_%7B10%7Db_%7B01%7D%20+%20a_%7B11%7Db_%7B11%7D)%0A%5Cend%7Bbmatrix%7D%0A=%0AC%0A"></p>
</div>
</div>
</div>
<p>Matrix multiplication simply involves taking the dot product of each row in the first matrix with each column in the second matrix.</p>
<p>We’ll need to use 3 iterators for this: one iterator <img src="https://latex.codecogs.com/png.latex?i"> to loop through the rows of <img src="https://latex.codecogs.com/png.latex?A">, another iterator <img src="https://latex.codecogs.com/png.latex?j"> to loop through the columns of <img src="https://latex.codecogs.com/png.latex?B">, and a third iterator <img src="https://latex.codecogs.com/png.latex?k"> to loop through the elements in a row and column.</p>
<blockquote class="blockquote">
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7Bfor%20row%20in%20%7D%20A"></p>
<p>&nbsp;&nbsp;<img src="https://latex.codecogs.com/png.latex?%5Ctext%7Bfor%20col%20in%20%7D%20B"></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;<img src="https://latex.codecogs.com/png.latex?%5Ctext%7Bfor%20ele%20in%20%7D%20A_%7B%5Ctext%7Brow%7D%7D%20%5Ctext%7B%20and%20%7D%20B_%7B%5Ctext%7Bcol%7D%7D"></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img src="https://latex.codecogs.com/png.latex?a_%7B%5Ctext%7Browele%7D%7D%20%5Ccdot%20b_%7B%5Ctext%7Belecol%7D%7D%20%5Cmathrel%7B+%7D=%20c_%7B%5Ctext%7Browcol%7D%7D"></p>
</blockquote>
<blockquote class="blockquote">
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7Bfor%20%7D%20i%20%5Ctext%7B%20in%20%7D%20A"></p>
<p>&nbsp;&nbsp;<img src="https://latex.codecogs.com/png.latex?%5Ctext%7Bfor%20%7D%20j%20%5Ctext%7B%20in%20%7D%20B"></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <img src="https://latex.codecogs.com/png.latex?%5Ctext%7Bfor%20%7D%20k%20%5Ctext%7B%20in%20%7D%20A_%7Bi%7D%20%5Ctext%7B%20and%20%7D%20B_%7Bj%7D"></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img src="https://latex.codecogs.com/png.latex?a_%7Bik%7D%20%5Ccdot%20b_%7Bkj%7D%20%5Cmathrel%7B+%7D=%20c_%7Bij%7D"></p>
</blockquote>
<p>Let’s focus in on the last line above.</p>
<p><img src="https://latex.codecogs.com/png.latex?%0Aa_%7Bik%7D%20%5Ccdot%20b_%7Bkj%7D%20%5Cmathrel%7B+%7D=%20c_%7Bij%7D%0A"></p>
<p>This can more succinctly be written in einsum notation as <img src="https://latex.codecogs.com/png.latex?ik,%20kj%20%5Crightarrow%20ij"> — for each row <img src="https://latex.codecogs.com/png.latex?i"> in <img src="https://latex.codecogs.com/png.latex?A">, and for each column <img src="https://latex.codecogs.com/png.latex?j"> in <img src="https://latex.codecogs.com/png.latex?B">, iterate through each element <img src="https://latex.codecogs.com/png.latex?k">, take their product, and sum the those products. The location of the output of the dot product in the output matrix <img src="https://latex.codecogs.com/png.latex?C"> is <img src="https://latex.codecogs.com/png.latex?c_%7Bij%7D">.</p>
</section>
</section>
<section id="various-examples" class="level2">
<h2 class="anchored" data-anchor-id="various-examples">Various Examples</h2>
<section id="d-operations" class="level3">
<h3 class="anchored" data-anchor-id="d-operations">1D Operations</h3>
<p><img src="https://latex.codecogs.com/png.latex?%0AA%20=%20%5Cbegin%7Bbmatrix%7D%201%20%5C%5C%202%20%5C%5C%203%20%5Cend%7Bbmatrix%7D,%20B%20=%20%5Cbegin%7Bbmatrix%7D%204%20%5C%5C%205%20%5C%5C%206%20%5Cend%7Bbmatrix%7D%0A"></p>
<section id="returning-a-view-of-a" class="level4">
<h4 class="anchored" data-anchor-id="returning-a-view-of-a">Returning a View of <img src="https://latex.codecogs.com/png.latex?A"></h4>
<section id="pseudocode" class="level5">
<h5 class="anchored" data-anchor-id="pseudocode"><strong>Pseudocode</strong></h5>
<p>For each row <img src="https://latex.codecogs.com/png.latex?i">, output the row.</p>
</section>
<section id="einsum-notation" class="level5">
<h5 class="anchored" data-anchor-id="einsum-notation"><strong>Einsum Notation</strong></h5>
<p><img src="https://latex.codecogs.com/png.latex?i%20%5Crightarrow%20i"></p>
<hr>
</section>
</section>
<section id="summing-the-values-of-a" class="level4">
<h4 class="anchored" data-anchor-id="summing-the-values-of-a">Summing the Values of <img src="https://latex.codecogs.com/png.latex?A"></h4>
<section id="pseudocode-1" class="level5">
<h5 class="anchored" data-anchor-id="pseudocode-1"><strong>Pseudocode</strong></h5>
<p>Iterate through each row <img src="https://latex.codecogs.com/png.latex?i">, and sum all rows.</p>
</section>
<section id="einsum-notation-1" class="level5">
<h5 class="anchored" data-anchor-id="einsum-notation-1"><strong>Einsum Notation</strong></h5>
<p><img src="https://latex.codecogs.com/png.latex?i%20%5Crightarrow%20%5Cphantom%7Bi%7D"></p>
<div class="callout callout-style-simple callout-note">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>A scalar is output, hence no output iterator.</p>
</div>
</div>
</div>
<hr>
</section>
</section>
<section id="hadamard-product-of-a-and-b" class="level4">
<h4 class="anchored" data-anchor-id="hadamard-product-of-a-and-b">Hadamard Product of <img src="https://latex.codecogs.com/png.latex?A"> and <img src="https://latex.codecogs.com/png.latex?B"></h4>
<section id="pseudocode-2" class="level5">
<h5 class="anchored" data-anchor-id="pseudocode-2"><strong>Pseudocode</strong></h5>
<p>For each row <img src="https://latex.codecogs.com/png.latex?i"> in <img src="https://latex.codecogs.com/png.latex?A"> and <img src="https://latex.codecogs.com/png.latex?B">, multiply them together.</p>
</section>
<section id="einsum-notation-2" class="level5">
<h5 class="anchored" data-anchor-id="einsum-notation-2"><strong>Einsum Notation</strong></h5>
<p><img src="https://latex.codecogs.com/png.latex?i,%20i%20%5Crightarrow%20i"></p>
<hr>
</section>
</section>
<section id="dot-product-of-a-and-b" class="level4">
<h4 class="anchored" data-anchor-id="dot-product-of-a-and-b">Dot Product of <img src="https://latex.codecogs.com/png.latex?A"> and <img src="https://latex.codecogs.com/png.latex?B"></h4>
<section id="pseudocode-3" class="level5">
<h5 class="anchored" data-anchor-id="pseudocode-3"><strong>Pseudocode</strong></h5>
<p>For each row <img src="https://latex.codecogs.com/png.latex?i"> in <img src="https://latex.codecogs.com/png.latex?A"> and <img src="https://latex.codecogs.com/png.latex?B">, multiply them together, and sum the products.</p>
</section>
<section id="einsum-notation-3" class="level5">
<h5 class="anchored" data-anchor-id="einsum-notation-3"><strong>Einsum Notation</strong></h5>
<p><img src="https://latex.codecogs.com/png.latex?i,%20i%20%5Crightarrow%20%5Cphantom%7Bi%7D"></p>
<div class="callout callout-style-simple callout-note">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>A scalar is output, hence no output iterator.</p>
</div>
</div>
</div>
<hr>
</section>
</section>
<section id="outer-product-of-a-and-b" class="level4">
<h4 class="anchored" data-anchor-id="outer-product-of-a-and-b"><a href="https://en.wikipedia.org/wiki/Outer_product">Outer Product</a> of <img src="https://latex.codecogs.com/png.latex?A"> and <img src="https://latex.codecogs.com/png.latex?B"></h4>
<section id="pseudocode-4" class="level5">
<h5 class="anchored" data-anchor-id="pseudocode-4"><strong>Pseudocode</strong></h5>
<p>For each row <img src="https://latex.codecogs.com/png.latex?i"> in <img src="https://latex.codecogs.com/png.latex?A">, multiply it with each row <img src="https://latex.codecogs.com/png.latex?j"> in <img src="https://latex.codecogs.com/png.latex?B">.</p>
</section>
<section id="einsum-notation-4" class="level5">
<h5 class="anchored" data-anchor-id="einsum-notation-4"><strong>Einsum Notation</strong></h5>
<p><img src="https://latex.codecogs.com/png.latex?i,%20j%20%5Crightarrow%20ij"></p>
<div class="callout callout-style-simple callout-note callout-titled">
<div class="callout-header d-flex align-content-center collapsed" data-bs-toggle="collapse" data-bs-target=".callout-3-contents" aria-controls="callout-3" aria-expanded="false" aria-label="Toggle callout">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-title-container flex-fill">
<span class="screen-reader-only">Note</span>Expanded example
</div>
<div class="callout-btn-toggle d-inline-block border-0 py-1 ps-1 pe-0 float-end"><i class="callout-toggle"></i></div>
</div>
<div id="callout-3" class="callout-3-contents callout-collapse collapse">
<div class="callout-body-container callout-body">
<p>The outer product involves multiplying each element in <img src="https://latex.codecogs.com/png.latex?A"> with all elements in <img src="https://latex.codecogs.com/png.latex?B">.</p>
<blockquote class="blockquote">
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7Bfor%20row%20in%20%7D%20A"></p>
<p>&nbsp;&nbsp;<img src="https://latex.codecogs.com/png.latex?%5Ctext%7Bfor%20another-row%20in%20%7D%20B"></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <img src="https://latex.codecogs.com/png.latex?a_%7B%5Ctext%7Brow%7D%7D%20%5Ccdot%20b_%7B%5Ctext%7Banother-row%7D%7D%20=%20c_%7B%5Ctext%7Browanother-row%7D%7D"></p>
</blockquote>
<blockquote class="blockquote">
<p><img src="https://latex.codecogs.com/png.latex?%5Ctext%7Bfor%20%7D%20i%20%5Ctext%7B%20in%20%7D%20A"></p>
<p>&nbsp;&nbsp; <img src="https://latex.codecogs.com/png.latex?%5Ctext%7Bfor%20%7D%20j%20%5Ctext%7B%20in%20%7D%20B"></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; <img src="https://latex.codecogs.com/png.latex?a_%7Bi%7D%20%5Ccdot%20b_%7Bj%7D%20=%20c_%7Bij%7D"></p>
</blockquote>
</div>
</div>
</div>
</section>
</section>
</section>
<section id="d-operations-1" class="level3">
<h3 class="anchored" data-anchor-id="d-operations-1">2D Operations</h3>
<p><img src="https://latex.codecogs.com/png.latex?%0AA%0A=%0A%5Cbegin%7Bbmatrix%7D%0A1%20&amp;%202%20&amp;%203%20%5C%5C%0A4%20&amp;%205%20&amp;%206%20%5C%5C%0A7%20&amp;%208%20&amp;%209%0A%5Cend%7Bbmatrix%7D%0A,%0AB%0A=%0A%5Cbegin%7Bbmatrix%7D%0A9%20&amp;%208%20&amp;%207%20%5C%5C%0A6%20&amp;%205%20&amp;%204%20%5C%5C%0A3%20&amp;%202%20&amp;%201%0A%5Cend%7Bbmatrix%7D%0A"></p>
<section id="return-a-view-of-a" class="level4">
<h4 class="anchored" data-anchor-id="return-a-view-of-a">Return a View of <img src="https://latex.codecogs.com/png.latex?A"></h4>
<section id="pseudocode-5" class="level5">
<h5 class="anchored" data-anchor-id="pseudocode-5"><strong>Pseudocode</strong></h5>
<p>For each row <img src="https://latex.codecogs.com/png.latex?i">, iterate through each column <img src="https://latex.codecogs.com/png.latex?j"> and output it.</p>
</section>
<section id="einsum-notation-5" class="level5">
<h5 class="anchored" data-anchor-id="einsum-notation-5"><strong>Einsum Notation</strong></h5>
<p><img src="https://latex.codecogs.com/png.latex?ij%20%5Crightarrow%20ij"></p>
<hr>
</section>
</section>
<section id="transpose-a" class="level4">
<h4 class="anchored" data-anchor-id="transpose-a">Transpose <img src="https://latex.codecogs.com/png.latex?A"></h4>
<section id="pseudocode-6" class="level5">
<h5 class="anchored" data-anchor-id="pseudocode-6"><strong>Pseudocode</strong></h5>
<p>For each row <img src="https://latex.codecogs.com/png.latex?i">, iterate through each column <img src="https://latex.codecogs.com/png.latex?j"> and output it in <img src="https://latex.codecogs.com/png.latex?C"> at row <img src="https://latex.codecogs.com/png.latex?j"> and column <img src="https://latex.codecogs.com/png.latex?i">.</p>
</section>
<section id="einsum-notation-6" class="level5">
<h5 class="anchored" data-anchor-id="einsum-notation-6"><strong>Einsum Notation</strong></h5>
<p><img src="https://latex.codecogs.com/png.latex?ij%20%5Crightarrow%20ji"></p>
<hr>
</section>
</section>
<section id="return-the-main-diagonal-of-a" class="level4">
<h4 class="anchored" data-anchor-id="return-the-main-diagonal-of-a">Return the Main Diagonal of <img src="https://latex.codecogs.com/png.latex?A"></h4>
<section id="pseudocode-7" class="level5">
<h5 class="anchored" data-anchor-id="pseudocode-7"><strong>Pseudocode</strong></h5>
<p>For each row <img src="https://latex.codecogs.com/png.latex?i">, iterate through each column <img src="https://latex.codecogs.com/png.latex?i"> and output it.</p>
</section>
<section id="einsum-notation-7" class="level5">
<h5 class="anchored" data-anchor-id="einsum-notation-7"><strong>Einsum Notation</strong></h5>
<p><img src="https://latex.codecogs.com/png.latex?ii%20%5Crightarrow%20i"></p>
<hr>
</section>
</section>
<section id="obtain-the-trace-of-a" class="level4">
<h4 class="anchored" data-anchor-id="obtain-the-trace-of-a">Obtain the Trace of <img src="https://latex.codecogs.com/png.latex?A"></h4>
<section id="pseudocode-8" class="level5">
<h5 class="anchored" data-anchor-id="pseudocode-8"><strong>Pseudocode</strong></h5>
<p>For each row <img src="https://latex.codecogs.com/png.latex?i">, iterate through each column <img src="https://latex.codecogs.com/png.latex?i"> and sum them.</p>
</section>
<section id="einsum-notation-8" class="level5">
<h5 class="anchored" data-anchor-id="einsum-notation-8"><strong>Einsum Notation</strong></h5>
<p><img src="https://latex.codecogs.com/png.latex?ii%20%5Crightarrow%20%5Cphantom%7Bi%7D"></p>
<div class="callout callout-style-simple callout-note">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>A scalar is output, hence no output iterator.</p>
</div>
</div>
</div>
<hr>
</section>
</section>
<section id="sum-the-rows-of-a" class="level4">
<h4 class="anchored" data-anchor-id="sum-the-rows-of-a">Sum the Rows of <img src="https://latex.codecogs.com/png.latex?A"></h4>
<section id="pseudocode-9" class="level5">
<h5 class="anchored" data-anchor-id="pseudocode-9"><strong>Pseudocode</strong></h5>
<p>For each row <img src="https://latex.codecogs.com/png.latex?i">, iterate through each column <img src="https://latex.codecogs.com/png.latex?j"> and sum them.</p>
</section>
<section id="einsum-notation-9" class="level5">
<h5 class="anchored" data-anchor-id="einsum-notation-9"><strong>Einsum Notation</strong></h5>
<p><img src="https://latex.codecogs.com/png.latex?ij%20%5Crightarrow%20i"></p>
<hr>
</section>
</section>
<section id="sum-the-columns-of-a" class="level4">
<h4 class="anchored" data-anchor-id="sum-the-columns-of-a">Sum the Columns of <img src="https://latex.codecogs.com/png.latex?A"></h4>
<section id="pseudocode-10" class="level5">
<h5 class="anchored" data-anchor-id="pseudocode-10"><strong>Pseudocode</strong></h5>
<p>For each column <img src="https://latex.codecogs.com/png.latex?j">, iterate through each row <img src="https://latex.codecogs.com/png.latex?i"> and sum them.</p>
</section>
<section id="einsum-notation-10" class="level5">
<h5 class="anchored" data-anchor-id="einsum-notation-10"><strong>Einsum Notation</strong></h5>
<p><img src="https://latex.codecogs.com/png.latex?ij%20%5Crightarrow%20j"></p>
<hr>
</section>
</section>
<section id="hadamard-product-of-a-and-b-1" class="level4">
<h4 class="anchored" data-anchor-id="hadamard-product-of-a-and-b-1">Hadamard Product of <img src="https://latex.codecogs.com/png.latex?A"> and <img src="https://latex.codecogs.com/png.latex?B"></h4>
<section id="pseudocode-11" class="level5">
<h5 class="anchored" data-anchor-id="pseudocode-11"><strong>Pseudocode</strong></h5>
<p>For each row <img src="https://latex.codecogs.com/png.latex?i"> in <img src="https://latex.codecogs.com/png.latex?A"> and <img src="https://latex.codecogs.com/png.latex?B">, iterate throuch each column <img src="https://latex.codecogs.com/png.latex?j">, and take their product.</p>
</section>
<section id="einsum-notation-11" class="level5">
<h5 class="anchored" data-anchor-id="einsum-notation-11"><strong>Einsum Notation</strong></h5>
<p><img src="https://latex.codecogs.com/png.latex?ij,%20ij%20%5Crightarrow%20ij"></p>
<hr>
</section>
</section>
<section id="hadamard-product-of-a-and-b-transposed-a-odot-bt" class="level4">
<h4 class="anchored" data-anchor-id="hadamard-product-of-a-and-b-transposed-a-odot-bt">Hadamard Product of <img src="https://latex.codecogs.com/png.latex?A"> and <img src="https://latex.codecogs.com/png.latex?B"> Transposed (<img src="https://latex.codecogs.com/png.latex?A%20%5Codot%20B%5E%7BT%7D">)</h4>
<section id="pseudocode-12" class="level5">
<h5 class="anchored" data-anchor-id="pseudocode-12"><strong>Pseudocode</strong></h5>
<p>For each row <img src="https://latex.codecogs.com/png.latex?i"> in <img src="https://latex.codecogs.com/png.latex?A">, and for each row <img src="https://latex.codecogs.com/png.latex?j"> in <img src="https://latex.codecogs.com/png.latex?B">, iterate through each column <img src="https://latex.codecogs.com/png.latex?j"> in <img src="https://latex.codecogs.com/png.latex?A"> and each column <img src="https://latex.codecogs.com/png.latex?i"> in <img src="https://latex.codecogs.com/png.latex?B">, and take their product.</p>
</section>
<section id="einsum-notation-12" class="level5">
<h5 class="anchored" data-anchor-id="einsum-notation-12"><strong>Einsum Notation</strong></h5>
<p><img src="https://latex.codecogs.com/png.latex?ij,%20ji%20%5Crightarrow%20ij"></p>
<hr>
</section>
</section>
<section id="matrix-product-of-a-and-b" class="level4">
<h4 class="anchored" data-anchor-id="matrix-product-of-a-and-b">Matrix Product of <img src="https://latex.codecogs.com/png.latex?A"> and <img src="https://latex.codecogs.com/png.latex?B"></h4>
<section id="pseudocode-13" class="level5">
<h5 class="anchored" data-anchor-id="pseudocode-13"><strong>Pseudocode</strong></h5>
<p>For each row <img src="https://latex.codecogs.com/png.latex?i"> in <img src="https://latex.codecogs.com/png.latex?A">, and for each column <img src="https://latex.codecogs.com/png.latex?j"> in <img src="https://latex.codecogs.com/png.latex?B">, iterate through each element <img src="https://latex.codecogs.com/png.latex?k">, take their product, and then sum those products.</p>
</section>
<section id="einsum-notation-13" class="level5">
<h5 class="anchored" data-anchor-id="einsum-notation-13"><strong>Einsum Notation</strong></h5>
<p><img src="https://latex.codecogs.com/png.latex?ik,%20kj%20%5Crightarrow%20ij"></p>
<hr>
</section>
</section>
<section id="each-row-of-a-multiplied-with-b" class="level4">
<h4 class="anchored" data-anchor-id="each-row-of-a-multiplied-with-b">Each Row of <img src="https://latex.codecogs.com/png.latex?A"> Multiplied with <img src="https://latex.codecogs.com/png.latex?B"></h4>
<section id="pseudocode-14" class="level5">
<h5 class="anchored" data-anchor-id="pseudocode-14"><strong>Pseudocode</strong></h5>
<!-- TODO: may want to reword this one. -->
<p>For each row <img src="https://latex.codecogs.com/png.latex?i"> in <img src="https://latex.codecogs.com/png.latex?A">, and for each row <img src="https://latex.codecogs.com/png.latex?j"> in <img src="https://latex.codecogs.com/png.latex?B">, iterate through each column <img src="https://latex.codecogs.com/png.latex?k"> and take their product.</p>
</section>
<section id="einsum-notation-14" class="level5">
<h5 class="anchored" data-anchor-id="einsum-notation-14"><strong>Einsum Notation</strong></h5>
<p><img src="https://latex.codecogs.com/png.latex?ik,%20jk%20%5Crightarrow%20ijk"></p>
<div class="callout callout-style-simple callout-note">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>A three dimensional tensor is output, hence the three output iterators.</p>
</div>
</div>
</div>
<hr>
</section>
</section>
<section id="every-element-of-a-multiplied-with-b" class="level4">
<h4 class="anchored" data-anchor-id="every-element-of-a-multiplied-with-b">Every Element of <img src="https://latex.codecogs.com/png.latex?A"> Multiplied with <img src="https://latex.codecogs.com/png.latex?B"></h4>
<section id="pseudocode-15" class="level5">
<h5 class="anchored" data-anchor-id="pseudocode-15"><strong>Pseudocode</strong></h5>
<!-- TODO: may want to reword this one. -->
<p>For each row <img src="https://latex.codecogs.com/png.latex?i"> in <img src="https://latex.codecogs.com/png.latex?A">, iterate through each column <img src="https://latex.codecogs.com/png.latex?j"> and multiply it with each row <img src="https://latex.codecogs.com/png.latex?k"> in <img src="https://latex.codecogs.com/png.latex?B"> by iterating through each column <img src="https://latex.codecogs.com/png.latex?l"> in that row <img src="https://latex.codecogs.com/png.latex?k">.</p>
</section>
<section id="einsum-notation-15" class="level5">
<h5 class="anchored" data-anchor-id="einsum-notation-15"><strong>Einsum Notation</strong></h5>
<p><img src="https://latex.codecogs.com/png.latex?ij,%20kl%20%5Crightarrow%20ijkl"></p>
<div class="callout callout-style-simple callout-note">
<div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"></i>
</div>
<div class="callout-body-container">
<p>A four dimensional tensor is output, hence the four output iterators.</p>
</div>
</div>
</div>
</section>
</section>
</section>
</section>
<section id="conclusion" class="level2">
<h2 class="anchored" data-anchor-id="conclusion">Conclusion</h2>
<p>And that’s that! The key is to think in terms of iterators that return locations in a matrix.</p>
<p>It may help to implement the operations above by yourself through pencil and paper, and in a programming languge too.</p>
<p>If you have any comments, questions, suggestions, feedback, criticisms, or corrections, please do post them down in the comment section below!</p>


</section>


<a onclick="window.scrollTo(0, 0); return false;" id="quarto-back-to-top"><i class="bi bi-arrow-up"></i> Back to top</a> ]]></description>
  <category>Mathematics</category>
  <category>Programming</category>
  <guid>https://forbo7.github.io/forblog/posts/16_einstein_summation_notation.html</guid>
  <pubDate>Tue, 06 Jun 2023 00:00:00 GMT</pubDate>
  <media:content url="https://forbo7.github.io/forblog/images/16_einstein_summation/thumbnail.png" medium="image" type="image/png" height="144" width="144"/>
</item>
</channel>
</rss>
